C#初級プログラミング PR

C#初心者のための基礎!例外Exceptionの意味と使い方をわかりやすく解説#30

記事内に商品プロモーションを含む場合があります

例外とは?

例外とは、エラー通知の事です。コーディングミスや、ユーザーの操作により、プログラムの続行が不可能となった場合は、ランタイムは例外を通知します。プログラマーは例外の通知をcatch構文で取得し、処理が続行できると判断した場合を続けることも可能です。

書き方

例外を捕捉する場合はtry、catch、finallyの構文を書きます。tryステートメントの中で例外が発生した場合は、catchステートメントに落ちてきます。finallyステートメントは、例外の有無にかかわらずに通る場所になるので、メモリの解放等、必ず必要な処理を記述するときに使用します。

例外の種類

例外はランタイムが通知するものと、我々プログラマーが自作するものがあります。

ランタイムが通知するものは、インデックスの境界外にアクセスしたときや、Nullにアクセスした場合などに次のような例外が通知されます。

  • SystemException
  • IndexOutOfRangeException
  • NullReferenceException
  • FormatException
  • DivideByZeroException
  • OverflowException等

例外を自作する場合

例外を自作する場合は、任意のクラスを作成し、Exceptionクラスを継承します。

ExceptionクラスにはMessageやInnerExceptionを指定できるため、必要な場合は自作Exceptionにコンストラクタを追加します。

例外の通知

任意の場所で例外を通知する場合はthrowキーワードを使って通知します。
throw new MyException(“xxxxx”);

サンプルコード

namespace CS30
{
    public  class Counter
    {
        private List _values = new List();

        public int GetData(int index)
        {
            return _values[index];
        }

        public int GetData2(int index)
        {
            try
            {
                return _values[index];
            }
            catch(ArgumentOutOfRangeException ex)
            {
                throw new MyException("マイエクセプション", ex);
            }
        }

        public int GetData3(int index)
        {
            return _values[index];

        }

    }
}

_valuesには値を設定していないので、インデックス指定をすると必ず例外が発生します。GetDataメソッドはcatchをしていないので、そのまま呼び出し元に通知されます。呼び出し元でもcatchしていない場合はアプリケーションが停止します。GetData2ではArgumentOutOfRangeExceptionで受けた例外をMyExceptionに変換しています。その際に、独自のメッセージと、ArgumentOutOfRangeExceptionをInnerExceptionに設定しています。InnerExceptionに設定しておくことで、元々の発生原因の例外を保持できるため、ログ出力等に使用できます。

namespace CS30
{
    public class MyException : Exception
    {
        public MyException(string message) : base(message)
        {
        }

        public MyException(string message,Exception innerException) :
            base(message, innerException)
        {
        }
    }
}

独自の例外はExceptionを継承し、Exceptionクラスのコンストラクタに存在するメッセージとインナーエクセプションを設定できるようにしています。

namespace CS30
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Counter c = new Counter();
            c.GetData(10);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                Counter c = new Counter();
                c.GetData(10);
            }
            catch(ArgumentOutOfRangeException ex)
            {
                this.Text = "インデックスのエラー";
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            try
            {
                Counter c = new Counter();
                c.GetData2(10);
            }
            catch (MyException ex)
            {
                this.Text = ex.Message;
                Console.WriteLine(ex.InnerException.Message);
            }
        }
    }
}

ボタンクリックの1では例外がどこでも捕捉されていないため、アプリケーションが終了します。ボタンクリックの2ではArgumentOutOfRangeExceptionがピンポイントで捕捉されているため、catchで書かれた処理が実施され、エラーにはなりません。 ボタンクリックの3では独自のMyExceptionが通知され、任意のメッセージと発生原因であるArgumentOutOfRangeExceptionのメッセージがコンソールに出力されます。

C#初心者のための基礎文法
Udemyで販売しているC#のコースを 1つプレゼントします!