例外とは?
例外とは、エラー通知の事です。コーディングミスや、ユーザーの操作により、プログラムの続行が不可能となった場合は、ランタイムは例外を通知します。プログラマーは例外の通知をcatch構文で取得し、処理が続行できると判断した場合を続けることも可能です。
書き方
例外を捕捉する場合はtry、catch、finallyの構文を書きます。tryステートメントの中で例外が発生した場合は、catchステートメントに落ちてきます。finallyステートメントは、例外の有無にかかわらずに通る場所になるので、メモリの解放等、必ず必要な処理を記述するときに使用します。
例外の種類
例外はランタイムが通知するものと、我々プログラマーが自作するものがあります。
ランタイムが通知するものは、インデックスの境界外にアクセスしたときや、Nullにアクセスした場合などに次のような例外が通知されます。
- SystemException
- IndexOutOfRangeException
- NullReferenceException
- FormatException
- DivideByZeroException
- OverflowException等
例外を自作する場合
例外を自作する場合は、任意のクラスを作成し、Exceptionクラスを継承します。
ExceptionクラスにはMessageやInnerExceptionを指定できるため、必要な場合は自作Exceptionにコンストラクタを追加します。
例外の通知
任意の場所で例外を通知する場合はthrowキーワードを使って通知します。
throw new MyException(“xxxxx”);
サンプルコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
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に設定しておくことで、元々の発生原因の例外を保持できるため、ログ出力等に使用できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
namespace CS30 { public class MyException : Exception { public MyException(string message) : base(message) { } public MyException(string message,Exception innerException) : base(message, innerException) { } } } |
独自の例外はExceptionを継承し、Exceptionクラスのコンストラクタに存在するメッセージとインナーエクセプションを設定できるようにしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
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#プログラマーのための正しい3層構造が分かる「C#アーキテクチャー解説動画」をここで公開しています。よかったら見てみてください。
- C#初心者のための基礎!C#文法2割の知識で8割の仕事をする方法!#1
- C#初心者のための基礎!ブロックと名前空間とクラスとメソッドを解説#2
- C#初心者のための基礎!#3値の扱い方。変数と定数をわかりやすく解説!
- C#初心者のための基礎!データ型の種類と使い分けをわかりやすく解説#4
- C#初心者のための基礎!値型と参照型の違いと使い方をわかりやすく解説#5
- C#初心者のための基礎!データ型の変換のやり方をわかりやすく解説#6
- C#初心者のための基礎!配列の使い方をわかりやすく解説#7
- C#初心者のための基礎!動的配列List<T>の使い方をわかりやすく解説#8
- C#初心者のための基礎!演算子の使い方をわかりやすく解説#9
- C#初心者のための基礎!if文とswich文の使い方をわかりやすく解説#10
- C#初心者のための基礎!while文の書き方と使い方をわかりやすく解説#11
- C#初心者のための基礎!do-While文の書き方と使い方をわかりやすく解説#12
- C#初心者のための基礎!for文の書き方と使い方をわかりやすく解説#13
- C#初心者のための基礎!foreach文の書き方と使い方をわかりやすく解説#14
- C#初心者のための基礎!オブジェクト指向の意味をわかりやすく解説#15
- C#初心者のための基礎!クラスの意味と使い方をわかりやすく解説#16
- C#初心者のための基礎!コンストラクタの意味と使い方をわかりやすく解説#17
- C#初心者のための基礎!アクセス修飾子の意味と使い方をわかりやすく解説#18
- C#初心者のための基礎!メソッドの意味と使い方をわかりやすく解説#19
- C#初心者のための基礎!フィールドの意味と使い方をわかりやすく解説#20
- C#初心者のための基礎!インスタンスの意味と使い方をわかりやすく解説#21
- C#初心者のための基礎!カプセル化の意味と使い方をわかりやすく解説#22
- C#初心者のための基礎!プロパティの意味と使い方をわかりやすく解説#23
- C#初心者のための基礎!Disposeとusingの意味と使い方を解説#24
- C#初心者のための基礎!staticスタティックの意味と使い方を解説#25
- C#初心者のための基礎!継承の意味と使い方をわかりやすく解説#26
- C#初心者のための基礎!override(オーバーライド)の使い方を解説#27
- C#初心者のための基礎!ポリモーフィズムとインタフェースの使い方を解説#28
- C#初心者のための基礎!ポリモーフィズムと抽象クラスの使い方を解説#29
- C#初心者のための基礎!例外Exceptionの意味と使い方をわかりやすく解説#30
参考図書
C#の文法
・実戦で役立つ C#プログラミングのイディオム/定石&パターン