C# 例外処理

例外は、プログラムの実行中に発生する問題です。C# の例外は、プログラムの実行時に発生する特殊な状況(たとえばゼロでの除算の試み)に対する応答です。

例外は、プログラムの制御をある部分から別の部分へ移す方法を提供します。C# の例外処理は、次の4つのキーワードに基づいて構築されています。try、catch、finallyとthrow。

  • trytry: try ブロックは、アクティブ化される特定の例外のコードブロックを識別します。その後に1つ以上の catch ブロックが続きます。
  • catchcatch: プログラムは例外ハンドラを使用して例外を捕捉します。catch キーワードは例外の捕捉を表します。
  • finallyfinally: finally ブロックは、例外がスローされるかどうかに関係なく、指定されたステートメントを実行するために使用されます。たとえば、ファイルを開いた場合、例外が発生するかどうかに関係なく、ファイルを閉じる必要があります。
  • throwthrow: 問題が発生すると、プログラムは例外をスローします。これは throw キーワードを使用して行います。

構文

ブロックに例外が発生すると仮定して、メソッドは try キーワードと catch キーワードを使用して例外を捕捉します。try/catch ブロック内のコードは保護されたコードであり、try/catch 構文は次のようになります。

try
{
   // 例外を引き起こすステートメント
}
catch( ExceptionName e1 )
{
   // エラー処理コード
}
catch( ExceptionName e2 )
{
   // エラー処理コード
}
catch( ExceptionName eN )
{
   // エラー処理コード
}
finally
{
   // 実行するステートメント
}

try ブロックが異なる状況で複数の例外を生成する場合に備えて、複数の catch ステートメントを列挙して、異なるタイプの例外を捕捉できます。

C# の例外クラス

C# の例外はクラスを使用して表されます。C# の例外クラスは、主に直接的または間接的にSystem.Exceptionクラスから派生しています。System.ApplicationExceptionとSystem.SystemExceptionクラスは、System.Exception クラスから派生した例外クラスです。

System.ApplicationExceptionクラスは、アプリケーションによって生成される例外をサポートします。したがって、プログラマーが定義する例外はすべてこのクラスから派生する必要があります。

System.SystemExceptionクラスは、すべての定義済みシステム例外の基本クラスです。

次の表に、System.SystemException クラスから派生したいくつかの定義済み例外クラスを示します。

例外クラス説明
System.IO.IOExceptionI/O エラーを処理します。
System.IndexOutOfRangeExceptionメソッドが範囲外の配列インデックスを参照したときに生成されるエラーを処理します。
System.ArrayTypeMismatchException配列の型が一致しないときに生成されるエラーを処理します。
System.NullReferenceExceptionnull オブジェクトを参照したときに生成されるエラーを処理します。
System.DivideByZeroExceptionゼロで除算したときに生成されるエラーを処理します。
System.InvalidCastException型変換中に生成されるエラーを処理します。
System.OutOfMemoryException空きメモリ不足によって生成されるエラーを処理します。
System.StackOverflowExceptionスタックオーバーフローによって生成されるエラーを処理します。

例外処理

C# は、try ブロックと catch ブロックの形式で構造化された例外処理方式を提供します。これらのブロックを使用して、主要なプログラムステートメントとエラー処理ステートメントを分離します。

これらのエラーハンドリングブロックは、try、catchとfinallyキーワードを使用して実装されています。以下は、ゼロ除算時に例外をスローする例です。

例

using System;
namespace ErrorHandlingApplication
{
    class DivNumbers
    {
        int result;
        DivNumbers()
        {
            result = 0;
        }
        public void division(int num1, int num2)
        {
            try
            {
                result = num1 / num2;
            }
            catch (DivideByZeroException e)
            {
                Console.WriteLine("Exception caught: {0}", e);
            }
            finally
            {
                Console.WriteLine("Result: {0}", result);
            }

        }
        static void Main(string[] args)
        {
            DivNumbers d = new DivNumbers();
            d.division(25, 0);
            Console.ReadKey();
        }
    }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます。

Exception caught: System.DivideByZeroException: Attempted to divide by zero. 
at ...
Result: 0

ユーザー定義例外の作成

独自の例外を定義することもできます。ユーザー定義の例外クラスは、ApplicationExceptionクラスから派生しています。

例

using System;
namespace UserDefinedException
{
   class TestTemperature
   {
      static void Main(string[] args)
      {
         Temperature temp = new Temperature();
         try
         {
            temp.showTemp();
         }
         catch(TempIsZeroException e)
         {
            Console.WriteLine("TempIsZeroException: {0}", e.Message);
         }
         Console.ReadKey();
      }
   }
}
public class TempIsZeroException: ApplicationException
{
   public TempIsZeroException(string message): base(message)
   {
   }
}
public class Temperature
{
   int temperature = 0;
   public void showTemp()
   {
      if(temperature == 0)
      {
         throw (new TempIsZeroException("Zero Temperature found"));
      }
      else
      {
         Console.WriteLine("Temperature: {0}", temperature);
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます。

TempIsZeroException: Zero Temperature found

オブジェクトのスロー

例外が直接的または間接的にSystem.Exceptionクラスから派生している場合は、オブジェクトをスローできます。catch ブロック内で throw ステートメントを使用して現在のオブジェクトをスローできます。次に示すとおりです。

Catch(Exception e)
{
   ...
   Throw e
}
その他の拡張