Exception クラス

定義

アプリケーションの実行中に発生したエラーを表します。

public ref class Exception
public ref class Exception : System::Runtime::Serialization::ISerializable
public ref class Exception : System::Runtime::InteropServices::_Exception, System::Runtime::Serialization::ISerializable
public class Exception
public class Exception : System.Runtime.Serialization.ISerializable
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.AutoDual)]
[System.Serializable]
public class Exception : System.Runtime.Serialization.ISerializable
[System.Serializable]
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)]
[System.Runtime.InteropServices.ComVisible(true)]
public class Exception : System.Runtime.InteropServices._Exception, System.Runtime.Serialization.ISerializable
[System.Serializable]
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)]
[System.Runtime.InteropServices.ComVisible(true)]
public class Exception : System.Runtime.Serialization.ISerializable
type Exception = class
type Exception = class
    interface ISerializable
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.AutoDual)>]
[<System.Serializable>]
type Exception = class
    interface ISerializable
[<System.Serializable>]
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type Exception = class
    interface ISerializable
    interface _Exception
[<System.Serializable>]
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type Exception = class
    interface ISerializable
Public Class Exception
Public Class Exception
Implements ISerializable
Public Class Exception
Implements _Exception, ISerializable
継承
Exception
派生
属性
実装

次の例は、 catch エラーを処理するために定義されているブロックを示してい ArithmeticException ます。 この catch ブロックは、 DivideByZeroException DivideByZeroException から派生 ArithmeticException し、 catch エラーのために明示的に定義されたブロックがないため、エラーもキャッチし DivideByZeroException ます。

using namespace System;
int main()
{
    int x = 0;
    try
    {
        int y = 100 / x;
    }
    catch ( ArithmeticException^ e ) 
    {
        Console::WriteLine( "ArithmeticException Handler: {0}", e );
    }
    catch ( Exception^ e ) 
    {
        Console::WriteLine( "Generic Exception Handler: {0}", e );
    }
}
/*
This code example produces the following results:

ArithmeticException Handler: System.DivideByZeroException: Attempted to divide by zero.
   at main()
 
*/
using System;

class ExceptionTestClass
{
   public static void Main()
   {
      int x = 0;
      try
      {
         int y = 100 / x;
      }
      catch (ArithmeticException e)
      {
         Console.WriteLine($"ArithmeticException Handler: {e}");
      }
      catch (Exception e)
      {
         Console.WriteLine($"Generic Exception Handler: {e}");
      }
   }	
}
/*
This code example produces the following results:

ArithmeticException Handler: System.DivideByZeroException: Attempted to divide by zero.
   at ExceptionTestClass.Main()

*/
Class ExceptionTestClass
   
   Public Shared Sub Main()
      Dim x As Integer = 0
      Try
         Dim y As Integer = 100 / x
      Catch e As ArithmeticException
         Console.WriteLine("ArithmeticException Handler: {0}", e.ToString())
      Catch e As Exception
         Console.WriteLine("Generic Exception Handler: {0}", e.ToString())
      End Try
   End Sub
End Class
'
'This code example produces the following results:
'
'ArithmeticException Handler: System.OverflowException: Arithmetic operation resulted in an overflow.
'   at ExceptionTestClass.Main()
'

注釈

このクラスは、すべての例外の基本クラスです。 エラーが発生した場合、システムまたは現在実行中のアプリケーションは、エラーに関する情報を含む例外をスローすることによって、エラーを報告します。 例外がスローされた後は、アプリケーションまたは既定の例外ハンドラーによって処理されます。

このセクションの内容は次のとおりです。

エラーと例外
Try ブロックと catch ブロック
例外の種類の機能
Exception クラスのプロパティ
パフォーマンスに関する考慮事項
例外を再スローする
標準例外の選択
カスタム例外の実装

エラーと例外

実行時エラーは、さまざまな理由で発生する可能性があります。 ただし、すべてのエラーをコード内で例外として処理する必要はありません。 ここでは、実行時に発生する可能性があるエラーのカテゴリと、それらに対処するための適切な方法を示します。

  • 使用エラー。 使用エラーは、例外が発生する可能性があるプログラムロジックのエラーを表します。 ただし、エラーは例外処理ではなく、問題のあるコードを変更することによって対処する必要があります。 たとえば、次の例のメソッドのオーバーライドは、 Object.Equals(Object) 引数が常に null 以外である必要があることを前提としてい obj ます。

    using System;
    
    public class Person
    {
       private string _name;
    
       public string Name
       {
          get { return _name; }
          set { _name = value; }
       }
    
       public override int GetHashCode()
       {
          return this.Name.GetHashCode();
       }
    
       public override bool Equals(object obj)
       {
          // This implementation contains an error in program logic:
          // It assumes that the obj argument is not null.
          Person p = (Person) obj;
          return this.Name.Equals(p.Name);
       }
    }
    
    public class Example
    {
       public static void Main()
       {
          Person p1 = new Person();
          p1.Name = "John";
          Person p2 = null;
    
          // The following throws a NullReferenceException.
          Console.WriteLine("p1 = p2: {0}", p1.Equals(p2));
       }
    }
    
    Public Class Person
       Private _name As String
       
       Public Property Name As String
          Get
             Return _name
          End Get
          Set
             _name = value
          End Set
       End Property
       
       Public Overrides Function Equals(obj As Object) As Boolean
          ' This implementation contains an error in program logic:
          ' It assumes that the obj argument is not null.
          Dim p As Person = CType(obj, Person)
          Return Me.Name.Equals(p.Name)
       End Function
    End Class
    
    Module Example
       Public Sub Main()
          Dim p1 As New Person()
          p1.Name = "John"
          Dim p2 As Person = Nothing
          
          ' The following throws a NullReferenceException.
          Console.WriteLine("p1 = p2: {0}", p1.Equals(p2))   
       End Sub
    End Module
    

    この例外は、がである場合に、 NullReferenceException obj オーバーライドを呼び出して null から再コンパイルする前に、明示的に null をテストするようにソースコードを変更することによって、結果を取り除くことができ Object.Equals ます。 次の例には、引数を処理する修正済みのソースコードが含まれてい null ます。

    using System;
    
    public class Person
    {
       private string _name;
    
       public string Name
       {
          get { return _name; }
          set { _name = value; }
       }
    
       public override int GetHashCode()
       {
          return this.Name.GetHashCode();
       }
    
       public override bool Equals(object obj)
       {
           // This implementation handles a null obj argument.
           Person p = obj as Person;
           if (p == null)
              return false;
           else
              return this.Name.Equals(p.Name);
       }
    }
    
    public class Example
    {
       public static void Main()
       {
          Person p1 = new Person();
          p1.Name = "John";
          Person p2 = null;
    
          Console.WriteLine("p1 = p2: {0}", p1.Equals(p2));
       }
    }
    // The example displays the following output:
    //        p1 = p2: False
    
    Public Class Person
       Private _name As String
       
       Public Property Name As String
          Get
             Return _name
          End Get
          Set
             _name = value
          End Set
       End Property
       
       Public Overrides Function Equals(obj As Object) As Boolean
          ' This implementation handles a null obj argument.
          Dim p As Person = TryCast(obj, Person)
          If p Is Nothing Then 
             Return False
          Else
             Return Me.Name.Equals(p.Name)
          End If
       End Function
    End Class
    
    Module Example
       Public Sub Main()
          Dim p1 As New Person()
          p1.Name = "John"
          Dim p2 As Person = Nothing
          
          Console.WriteLine("p1 = p2: {0}", p1.Equals(p2))   
       End Sub
    End Module
    ' The example displays the following output:
    '       p1 = p2: False
    

    使用エラーに対して例外処理を使用する代わりに、メソッドを使用して Debug.Assert デバッグビルドの使用エラーを識別し、メソッドを使用して Trace.Assert デバッグビルドとリリースビルドの両方で使用エラーを識別することができます。 詳細については、「マネージド コードのアサーション」を参照してください。

  • プログラムエラーです。 プログラムエラーは、バグのないコードを記述することによって必ずしも回避できないランタイムエラーです。

    場合によっては、プログラムエラーによって予期されるエラー条件またはルーチンエラーが反映されることがあります。 この場合、プログラムエラーに対処するために例外処理を使用せずに、操作を再試行することができます。 たとえば、ユーザーが特定の形式で日付を入力することが想定されている場合、メソッドを呼び出すことによって、日付文字列を解析できます。このメソッドは、メソッドを使用する代わりに、 DateTime.TryParseExact Boolean 解析操作が成功したかどうかを示す値を返し DateTime.ParseExact FormatException DateTime ます。 同様に、存在しないファイルを開こうとした場合は、最初にメソッドを呼び出して、 File.Exists ファイルが存在するかどうかを確認し、存在しない場合は、作成するかどうかをユーザーに確認することができます。

    それ以外の場合、プログラムエラーには、コードで処理できる予期しないエラー状態が反映されます。 たとえば、ファイルが存在することを確認した場合でも、ファイルを開く前に削除するか、破損している可能性があります。 この場合、オブジェクトをインスタンス化するか、メソッドを呼び出すことによってファイルを開こうとすると、 StreamReader Open 例外がスローされる可能性があり FileNotFoundException ます。 このような場合は、例外処理を使用してエラーから復旧する必要があります。

  • システムエラー。 システム障害は、プログラムによって意味のない方法で処理できない実行時エラーです。 たとえば、 OutOfMemoryException 共通言語ランタイムが追加のメモリを割り当てられない場合、どのメソッドでも例外がスローされる可能性があります。 通常、システム障害は例外処理を使用しても処理されません。 代わりに、などのイベントを使用 AppDomain.UnhandledException し、メソッドを呼び出して Environment.FailFast 例外情報をログに記録し、アプリケーションが終了する前にエラーをユーザーに通知することができます。

Try ブロックと catch ブロック

共通言語ランタイムは、例外をオブジェクトとして表現し、プログラムコードと例外処理コードをブロックおよびブロックに分離することに基づいて、例外処理モデルを提供し try catch ます。 1つまたは複数の catch ブロックがあり、それぞれが特定の種類の例外を処理するように設計されているか、別のブロックよりも具体的な例外をキャッチするように設計されているブロックがあります。

アプリケーションコードのブロックの実行中に発生した例外をアプリケーションが処理する場合は、コードをステートメント内に配置し、ブロックと呼ばれる必要があり try try ます。 ブロックによってスローされた例外を処理するアプリケーションコード try は、ステートメント内に配置され、 catch ブロックと呼ばれ catch ます。 0個以上のブロック catch がブロックに関連付けられており、各ブロックには、 try 処理する catch 例外の種類を決定する型フィルターが含まれています。

ブロックで例外が発生すると try 、システムは、 catch catch 例外を処理するブロックを見つけるまで、関連付けられているブロックをアプリケーションコードに出現する順序で検索します。 catch T Catch ブロックの型フィルターで T またはから派生した型が指定されている場合、ブロックは型の例外を処理し T ます。 例外を処理する最初のブロックが検索された後、システムは検索を停止し catch ます。 このため、アプリケーションコードでは、 catch catch このセクションの後の例に示すように、その基本型を処理するブロックの前に、型を処理するブロックを指定する必要があります。 を処理する catch ブロック System.Exception が最後に指定されています。

catch現在のブロックに関連付けられているブロックが例外を処理しない場合、現在の try try ブロックが現在の呼び出しの他のブロック内で入れ子になっていると、次のブロックに try catch 関連付けられているブロックが try 検索されます。 例外のブロックが見つからない場合は、 catch 現在の呼び出しで前の入れ子レベルが検索されます。 現在の catch 呼び出しで例外のブロックが見つからない場合は、例外が呼び出し履歴に渡され、例外を処理するブロックの前のスタックフレームが検索され catch ます。 呼び出し履歴の検索は、例外が処理されるか、または呼び出し履歴にフレームが存在しなくなるまで続行されます。 例外を処理するブロックを検索せずにコールスタックの一番上に到達した場合 catch 、既定の例外ハンドラーはそれを処理してアプリケーションを終了します。

例外の種類の機能

例外の種類では、次の機能がサポートされます。

  • 人間が判読できる、エラーを説明するテキスト。 例外が発生すると、ランタイムは、エラーの性質をユーザーに通知し、問題を解決するためのアクションを提案するためのテキストメッセージを使用できるようにします。 このテキストメッセージは、 Message exception オブジェクトのプロパティに保持されます。 例外オブジェクトの作成時に、その特定の例外の詳細を記述するテキスト文字列をコンストラクターに渡すことができます。 コンストラクターにエラーメッセージ引数が指定されていない場合は、既定のエラーメッセージが使用されます。 詳細については、Message プロパティを参照してください。

  • 例外がスローされたときの呼び出し履歴の状態。 プロパティは、 StackTrace コード内でエラーが発生した場所を判断するために使用できるスタックトレースを保持します。 スタックトレースでは、呼び出されたすべてのメソッドと、呼び出しが行われたソースファイル内の行番号が一覧表示されます。

Exception クラスのプロパティ

クラスには、 Exception コードの場所、型、ヘルプファイル、および例外の理由 (、、、、、、、 StackTrace InnerException Message HelpLink HResult Source TargetSite および Data ) を識別するための多数のプロパティが含まれています。

2つ以上の例外の間に因果関係が存在する場合、 InnerException プロパティはこの情報を保持します。 外側の例外は、この内部例外に応答してスローされます。 外側の例外を処理するコードでは、前の内部例外の情報を使用して、エラーをより適切に処理できます。 例外に関する補足情報は、プロパティのキーと値のペアのコレクションとして格納でき Data ます。

例外オブジェクトの作成時にコンストラクターに渡されるエラーメッセージ文字列はローカライズされ、クラスを使用してリソースファイルから渡すことができ ResourceManager ます。 ローカライズされたリソースの詳細については、「 サテライトアセンブリの作成 」および「 リソースのパッケージ化と配置 」のトピックを参照してください。

例外が発生した理由に関する詳細情報をユーザーに提供するために、 HelpLink プロパティはヘルプファイルへの URL (または URN) を保持できます。

クラスは、 Exception 値0x80131500 を持つ HRESULT COR_E_EXCEPTION を使用します。

クラスのインスタンスの初期プロパティ値の一覧につい Exception ては、「コンストラクター」を参照してください Exception

パフォーマンスに関する考慮事項

例外をスローまたは処理すると、大量のシステムリソースと実行時間が消費されます。 例外をスローするのは、予測可能なイベントやフロー制御を処理するのではなく、本当に特別な条件を処理する場合のみです。 たとえば、クラスライブラリを開発している場合など、メソッドの引数が無効である場合は例外をスローすることが妥当です。有効なパラメーターを使用してメソッドを呼び出すことが想定されているためです。 無効なメソッド引数が使用エラーの結果でない場合は、異常が発生したことを意味します。 逆に、ユーザーの入力が無効な場合は、ユーザーが無効なデータを頻繁に入力することが予想されるため、例外をスローしません。 代わりに、ユーザーが有効な入力を入力できるように再試行メカニズムを提供します。 また、例外を使用して使用エラーを処理する必要もありません。 代わりに、 アサーション を使用して、使用エラーを特定し、修正します。

また、リターンコードが十分である場合は、例外をスローしないでください。リターンコードを例外に変換しないでください。また、例外を定期的にキャッチせず、無視して処理を続行することもありません。

例外を再スローする

多くの場合、例外ハンドラーは、例外を呼び出し元に渡すだけです。 これは、最も頻繁に発生します。

  • さらに、クラスライブラリは、.NET Framework クラスライブラリまたはその他のクラスライブラリのメソッドの呼び出しをラップします。

  • 致命的な例外が発生したアプリケーションまたはライブラリ。 例外ハンドラーは例外をログに記録し、例外を再スローすることができます。

例外を再スローするには、C# ではthrowステートメントを使用し、式を含まない Visual Basic ではthrowステートメントを使用することをお勧めします。 これにより、例外が呼び出し元に反映されるときに、すべてのコールスタック情報が保持されます。 次の例を使って説明します。 文字列拡張メソッドは、 FindOccurrences 引数を事前に検証せずに、の1つ以上の呼び出しをラップし String.IndexOf(String, Int32) ます。

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

public static class Library
{
   public static int[] FindOccurrences(this String s, String f)
   {
      var indexes = new List<int>();
      int currentIndex = 0;
      try {
         while (currentIndex >= 0 && currentIndex < s.Length) {
            currentIndex = s.IndexOf(f, currentIndex);
            if (currentIndex >= 0) {
               indexes.Add(currentIndex);
               currentIndex++;
            }
         }
      }
      catch (ArgumentNullException e) {
         // Perform some action here, such as logging this exception.

         throw;
      }
      return indexes.ToArray();
   }
}
Imports System.Collections.Generic
Imports System.Runtime.CompilerServices

Public Module Library
   <Extension()>
   Public Function FindOccurrences(s As String, f As String) As Integer()
      Dim indexes As New List(Of Integer)
      Dim currentIndex As Integer = 0
      Try
         Do While currentIndex >= 0 And currentIndex < s.Length
            currentIndex = s.IndexOf(f, currentIndex)
            If currentIndex >= 0 Then
               indexes.Add(currentIndex)
               currentIndex += 1
            End If
         Loop
      Catch e As ArgumentNullException
         ' Perform some action here, such as logging this exception.
         
         Throw
      End Try
      Return indexes.ToArray()
   End Function
End Module

次に、呼び出し元は FindOccurrences 2 回を呼び出します。 の2回目の呼び出しで FindOccurrences は、呼び出し元はを null 検索文字列として渡します。これにより、 String.IndexOf(String, Int32) メソッドは例外をスロー ArgumentNullException します。 この例外は、メソッドによって処理され、 FindOccurrences 呼び出し元に戻されます。 Throw ステートメントは式なしで使用されるため、この例の出力は、呼び出し履歴が保持されていることを示しています。

public class Example
{
   public static void Main()
   {
      String s = "It was a cold day when...";
      int[] indexes = s.FindOccurrences("a");
      ShowOccurrences(s, "a", indexes);
      Console.WriteLine();

      String toFind = null;
      try {
         indexes = s.FindOccurrences(toFind);
         ShowOccurrences(s, toFind, indexes);
      }
      catch (ArgumentNullException e) {
         Console.WriteLine("An exception ({0}) occurred.",
                           e.GetType().Name);
         Console.WriteLine("Message:\n   {0}\n", e.Message);
         Console.WriteLine("Stack Trace:\n   {0}\n", e.StackTrace);
      }
   }

   private static void ShowOccurrences(String s, String toFind, int[] indexes)
   {
      Console.Write("'{0}' occurs at the following character positions: ",
                    toFind);
      for (int ctr = 0; ctr < indexes.Length; ctr++)
         Console.Write("{0}{1}", indexes[ctr],
                       ctr == indexes.Length - 1 ? "" : ", ");

      Console.WriteLine();
   }
}
// The example displays the following output:
//    'a' occurs at the following character positions: 4, 7, 15
//
//    An exception (ArgumentNullException) occurred.
//    Message:
//       Value cannot be null.
//    Parameter name: value
//
//    Stack Trace:
//          at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
//    ngComparison comparisonType)
//       at Library.FindOccurrences(String s, String f)
//       at Example.Main()
Module Example
   Public Sub Main()
      Dim s As String = "It was a cold day when..."
      Dim indexes() As Integer = s.FindOccurrences("a")
      ShowOccurrences(s, "a", indexes)
      Console.WriteLine()

      Dim toFind As String = Nothing
      Try
         indexes = s.FindOccurrences(toFind)
         ShowOccurrences(s, toFind, indexes)
      Catch e As ArgumentNullException
         Console.WriteLine("An exception ({0}) occurred.",
                           e.GetType().Name)
         Console.WriteLine("Message:{0}   {1}{0}", vbCrLf, e.Message)
         Console.WriteLine("Stack Trace:{0}   {1}{0}", vbCrLf, e.StackTrace)
      End Try
   End Sub
   
   Private Sub ShowOccurrences(s As String, toFind As String, indexes As Integer())
      Console.Write("'{0}' occurs at the following character positions: ",
                    toFind)
      For ctr As Integer = 0 To indexes.Length - 1
         Console.Write("{0}{1}", indexes(ctr),
                       If(ctr = indexes.Length - 1, "", ", "))
      Next
      Console.WriteLine()
   End Sub
End Module
' The example displays the following output:
'    'a' occurs at the following character positions: 4, 7, 15
'
'    An exception (ArgumentNullException) occurred.
'    Message:
'       Value cannot be null.
'    Parameter name: value
'
'    Stack Trace:
'          at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
'    ngComparison comparisonType)
'       at Library.FindOccurrences(String s, String f)
'       at Example.Main()

これに対し、を使用して例外が再スローされる場合は、

throw e;
Throw e  

ステートメント、完全な呼び出し履歴は保持されず、例では次の出力が生成されます。

'a' occurs at the following character positions: 4, 7, 15  

An exception (ArgumentNullException) occurred.  
Message:  
   Value cannot be null.  
Parameter name: value  

Stack Trace:  
      at Library.FindOccurrences(String s, String f)  
   at Example.Main()  

もう少し厄介な方法は、新しい例外をスローし、元の例外の呼び出し履歴情報を内部例外で保持することです。 呼び出し元は、新しい例外のプロパティを使用して、 InnerException 元の例外に関するスタックフレームおよびその他の情報を取得できます。 この場合、throw ステートメントは次のようになります。

throw new ArgumentNullException("You must supply a search string.",
                                e);
Throw New ArgumentNullException("You must supply a search string.",
                                e)

例外を処理するユーザーコードは、 InnerException 次の例外ハンドラーに示すように、プロパティに元の例外に関する情報が含まれていることを認識している必要があります。

try {
   indexes = s.FindOccurrences(toFind);
   ShowOccurrences(s, toFind, indexes);
}
catch (ArgumentNullException e) {
   Console.WriteLine("An exception ({0}) occurred.",
                     e.GetType().Name);
   Console.WriteLine("   Message:\n{0}", e.Message);
   Console.WriteLine("   Stack Trace:\n   {0}", e.StackTrace);
   Exception ie = e.InnerException;
   if (ie != null) {
      Console.WriteLine("   The Inner Exception:");
      Console.WriteLine("      Exception Name: {0}", ie.GetType().Name);
      Console.WriteLine("      Message: {0}\n", ie.Message);
      Console.WriteLine("      Stack Trace:\n   {0}\n", ie.StackTrace);
   }
}
// The example displays the following output:
//    'a' occurs at the following character positions: 4, 7, 15
//
//    An exception (ArgumentNullException) occurred.
//       Message: You must supply a search string.
//
//       Stack Trace:
//          at Library.FindOccurrences(String s, String f)
//       at Example.Main()
//
//       The Inner Exception:
//          Exception Name: ArgumentNullException
//          Message: Value cannot be null.
//    Parameter name: value
//
//          Stack Trace:
//          at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
//    ngComparison comparisonType)
//       at Library.FindOccurrences(String s, String f)
Try
   indexes = s.FindOccurrences(toFind)
   ShowOccurrences(s, toFind, indexes)
Catch e As ArgumentNullException
   Console.WriteLine("An exception ({0}) occurred.",
                     e.GetType().Name)
   Console.WriteLine("   Message: {1}{0}", vbCrLf, e.Message)
   Console.WriteLine("   Stack Trace:{0}   {1}{0}", vbCrLf, e.StackTrace)
   Dim ie As Exception = e.InnerException
   If ie IsNot Nothing Then
      Console.WriteLine("   The Inner Exception:")
      Console.WriteLine("      Exception Name: {0}", ie.GetType().Name)
      Console.WriteLine("      Message: {1}{0}", vbCrLf, ie.Message)
      Console.WriteLine("      Stack Trace:{0}   {1}{0}", vbCrLf, ie.StackTrace)
   End If
End Try
' The example displays the following output:
'       'a' occurs at the following character positions: 4, 7, 15
'
'       An exception (ArgumentNullException) occurred.
'          Message: You must supply a search string.
'
'          Stack Trace:
'             at Library.FindOccurrences(String s, String f)
'          at Example.Main()
'
'          The Inner Exception:
'             Exception Name: ArgumentNullException
'             Message: Value cannot be null.
'       Parameter name: value
'
'             Stack Trace:
'             at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
'       ngComparison comparisonType)
'          at Library.FindOccurrences(String s, String f)

標準例外の選択

例外をスローする必要がある場合は、カスタム例外を実装するのではなく、.NET Framework で既存の例外の種類を使用することがよくあります。 次の2つの条件下では、標準の例外の種類を使用する必要があります。

  • 使用エラー (つまり、メソッドを呼び出している開発者によって作成されたプログラムロジックのエラー) によって発生した例外をスローしています。 通常は、、、、などの例外をスローし ArgumentException ArgumentNullException InvalidOperationException NotSupportedException ます。 例外オブジェクトをインスタンス化するときに例外オブジェクトのコンストラクターに渡す文字列は、開発者が修正できるようにエラーを記述する必要があります。 詳細については、Message プロパティを参照してください。

  • 既存の .NET Framework 例外を使用して呼び出し元に伝達できるエラーを処理しています。 できるだけ多くの派生された例外をスローする必要があります。 たとえば、メソッドで、引数が列挙型の有効なメンバーである必要がある場合は、で InvalidEnumArgumentException はなく、(最も派生クラスの) をスローする必要があり ArgumentException ます。

次の表に、一般的な例外の種類と、それらをスローする条件を示します。

例外 条件
ArgumentException メソッドに渡された null 以外の引数が無効です。
ArgumentNullException メソッドに渡される引数は null です。
ArgumentOutOfRangeException 引数が有効な値の範囲外です。
DirectoryNotFoundException ディレクトリパスの一部が無効です。
DivideByZeroException 整数または Decimal 除算演算の分母が0です。
DriveNotFoundException ドライブが使用できないか、または存在しません。
FileNotFoundException ファイルが存在しません。
FormatException 値は、などの変換メソッドによって文字列から変換される適切な形式ではありません Parse
IndexOutOfRangeException インデックスが配列またはコレクションの範囲外です。
InvalidOperationException メソッドの呼び出しは、オブジェクトの現在の状態では無効です。
KeyNotFoundException コレクション内のメンバーにアクセスするために指定されたキーが見つかりません。
NotImplementedException メソッドまたは操作が実装されていません。
NotSupportedException メソッドまたは操作はサポートされていません。
ObjectDisposedException 破棄されたオブジェクトに対して操作が実行されます。
OverflowException 算術演算、キャスト演算、または変換操作を実行すると、オーバーフローが発生します。
PathTooLongException パスまたはファイル名がシステム定義の最大長を超えています。
PlatformNotSupportedException この操作は、現在のプラットフォームではサポートされていません。
RankException 次元の数が正しくない配列がメソッドに渡されました。
TimeoutException 操作に割り当てられた時間間隔が経過しました。
UriFormatException 無効な Uniform Resource Identifier (URI) が使用されています。

カスタム例外の実装

次の場合、既存の .NET Framework 例外を使用してエラー条件を処理するのは適切ではありません。

  • 例外が、既存の .NET Framework 例外にマップできない一意のプログラムエラーを反映した場合。

  • 既存の .NET Framework 例外に適した処理とは異なる処理が例外に必要な場合、または同様の例外から例外を明確する必要がある場合。 たとえば、 ArgumentOutOfRangeException ターゲットの整数型の範囲外にある文字列の数値表現を解析するときに例外をスローした場合、呼び出し元がメソッドの呼び出し時に適切な制約値を指定していないというエラーに対して、同じ例外を使用する必要はありません。

クラスは、 Exception .NET Framework 内のすべての例外の基本クラスです。 多くの派生クラスは、クラスのメンバーの継承された動作に依存して Exception います。のメンバーをオーバーライドし Exception たり、一意のメンバーを定義したりすることはありません。

独自の例外クラスを定義するには、次のようにします。

  1. を継承するクラスを定義 Exception します。 必要に応じて、クラスに必要な一意のメンバーを定義して、例外に関する追加情報を提供します。 たとえば、クラスには、引数によって ArgumentException ParamName 例外が発生したパラメーターの名前を指定するプロパティが含まれています。また、プロパティには、 RegexMatchTimeoutException タイムアウト間隔を示すプロパティが含まれてい MatchTimeout ます。

  2. 必要に応じて、変更または変更する機能を持つ継承されたメンバーをオーバーライドします。 の既存の派生クラスのほとんど Exception は、継承されたメンバーの動作をオーバーライドしないことに注意してください。

  3. カスタム例外オブジェクトがシリアル化可能であるかどうかを判断します。 シリアル化を使用すると、例外に関する情報を保存し、例外情報をサーバーとクライアントプロキシがリモート処理コンテキストで共有できるようになります。 例外オブジェクトをシリアル化できるようにするには、属性でマークし SerializableAttribute ます。

  4. Exception クラスのコンストラクターを定義します。 通常、例外クラスには、次のコンストラクターが1つ以上含まれています。

    • Exception()。既定値を使用して、新しい exception オブジェクトのプロパティを初期化します。

    • Exception(String)。指定したエラーメッセージを使用して、新しい例外オブジェクトを初期化します。

    • Exception(String, Exception)。指定したエラーメッセージと内部例外を使用して、新しい例外オブジェクトを初期化します。

    • Exception(SerializationInfo, StreamingContext)。これは、 protected シリアル化されたデータから新しい例外オブジェクトを初期化するコンストラクターです。 例外オブジェクトをシリアル化可能にすることを選択した場合は、このコンストラクターを実装する必要があります。

次の例は、カスタム例外クラスの使用方法を示しています。 これは、 NotPrimeException クライアントが素数ではない開始番号を指定して素数のシーケンスを取得しようとしたときにスローされる例外を定義します。 例外は、 NonPrime 例外の原因となった素数以外の数値を返す新しいプロパティを定義します。 保護されたパラメーターなしのコンストラクターと、 SerializationInfo シリアル化のパラメーターとパラメーターを持つコンストラクターを実装 StreamingContext するだけでなく、 NotPrimeException クラスは、プロパティをサポートするために3つの追加のコンストラクターを定義し NonPrime ます。 各コンストラクターは、非素数の値を保持するだけでなく、基底クラスのコンストラクターも呼び出します。 NotPrimeExceptionクラスは、属性でもマークされ SerializableAttribute ます。

using System;
using System.Runtime.Serialization;

[Serializable()]
public class NotPrimeException : Exception
{
   private int notAPrime;

   protected NotPrimeException()
      : base()
   { }

   public NotPrimeException(int value) :
      base(String.Format("{0} is not a prime number.", value))
   {
      notAPrime = value;
   }

   public NotPrimeException(int value, string message)
      : base(message)
   {
      notAPrime = value;
   }

   public NotPrimeException(int value, string message, Exception innerException) :
      base(message, innerException)
   {
      notAPrime = value;
   }

   protected NotPrimeException(SerializationInfo info,
                               StreamingContext context)
      : base(info, context)
   { }

   public int NonPrime
   { get { return notAPrime; } }
}
Imports System.Runtime.Serialization

<Serializable()> _
Public Class NotPrimeException : Inherits Exception
   Private notAPrime As Integer

   Protected Sub New()
      MyBase.New()
   End Sub

   Public Sub New(value As Integer)
      MyBase.New(String.Format("{0} is not a prime number.", value))
      notAPrime = value
   End Sub

   Public Sub New(value As Integer, message As String)
      MyBase.New(message)
      notAPrime = value
   End Sub

   Public Sub New(value As Integer, message As String, innerException As Exception)
      MyBase.New(message, innerException)
      notAPrime = value
   End Sub

   Protected Sub New(info As SerializationInfo,
                     context As StreamingContext)
      MyBase.New(info, context)
   End Sub

   Public ReadOnly Property NonPrime As Integer
      Get
         Return notAPrime
      End Get
   End Property
End Class

PrimeNumberGenerator次の例に示すクラスでは、ありのエラトステネスを使用して、2からの素数のシーケンスを、クラスコンストラクターの呼び出しでクライアントによって指定された制限に計算します。 メソッドは、 GetPrimesFrom 指定された下限を超えるすべての素数を返しますが、 NotPrimeException 下限の値が素数でない場合はをスローします。

using System;
using System.Collections.Generic;

[Serializable]
public class PrimeNumberGenerator
{
   private const int START = 2;
   private int maxUpperBound = 10000000;
   private int upperBound;
   private bool[] primeTable;
   private List<int> primes = new List<int>();

   public PrimeNumberGenerator(int upperBound)
   {
      if (upperBound > maxUpperBound)
      {
         string message = String.Format(
                           "{0} exceeds the maximum upper bound of {1}.",
                           upperBound, maxUpperBound);
         throw new ArgumentOutOfRangeException(message);
      }
      this.upperBound = upperBound;
      // Create array and mark 0, 1 as not prime (True).
      primeTable = new bool[upperBound + 1];
      primeTable[0] = true;
      primeTable[1] = true;

      // Use Sieve of Eratosthenes to determine prime numbers.
      for (int ctr = START; ctr <= (int)Math.Ceiling(Math.Sqrt(upperBound));
            ctr++)
      {
         if (primeTable[ctr]) continue;

         for (int multiplier = ctr; multiplier <= upperBound / ctr; multiplier++)
            if (ctr * multiplier <= upperBound) primeTable[ctr * multiplier] = true;
      }
      // Populate array with prime number information.
      int index = START;
      while (index != -1)
      {
         index = Array.FindIndex(primeTable, index, (flag) => !flag);
         if (index >= 1)
         {
            primes.Add(index);
            index++;
         }
      }
   }

   public int[] GetAllPrimes()
   {
      return primes.ToArray();
   }

   public int[] GetPrimesFrom(int prime)
   {
      int start = primes.FindIndex((value) => value == prime);
      if (start < 0)
         throw new NotPrimeException(prime, String.Format("{0} is not a prime number.", prime));
      else
         return primes.FindAll((value) => value >= prime).ToArray();
   }
}
Imports System.Collections.Generic

<Serializable()> Public Class PrimeNumberGenerator
   Private Const START As Integer = 2
   Private maxUpperBound As Integer = 10000000
   Private upperBound As Integer
   Private primeTable() As Boolean
   Private primes As New List(Of Integer)

   Public Sub New(upperBound As Integer)
      If upperBound > maxUpperBound Then
         Dim message As String = String.Format(
             "{0} exceeds the maximum upper bound of {1}.",
             upperBound, maxUpperBound)
         Throw New ArgumentOutOfRangeException(message)
      End If
      Me.upperBound = upperBound
      ' Create array and mark 0, 1 as not prime (True).
      ReDim primeTable(upperBound)
      primeTable(0) = True
      primeTable(1) = True

      ' Use Sieve of Eratosthenes to determine prime numbers.
      For ctr As Integer = START To CInt(Math.Ceiling(Math.Sqrt(upperBound)))
         If primeTable(ctr) Then Continue For

         For multiplier As Integer = ctr To CInt(upperBound \ ctr)
            If ctr * multiplier <= upperBound Then primeTable(ctr * multiplier) = True
         Next
      Next
      ' Populate array with prime number information.
      Dim index As Integer = START
      Do While index <> -1
         index = Array.FindIndex(primeTable, index, Function(flag)
                                                       Return Not flag
                                                    End Function)
         If index >= 1 Then
            primes.Add(index)
            index += 1
         End If
      Loop
   End Sub

   Public Function GetAllPrimes() As Integer()
      Return primes.ToArray()
   End Function

   Public Function GetPrimesFrom(prime As Integer) As Integer()
      Dim start As Integer = primes.FindIndex(Function(value)
                                                 Return value = prime
                                              End Function)
      If start < 0 Then
         Throw New NotPrimeException(prime, String.Format("{0} is not a prime number.", prime))
      Else
         Return primes.FindAll(Function(value)
                                  Return value >= prime
                               End Function).ToArray()
      End If
   End Function
End Class

次の例では、2つ GetPrimesFrom のメソッドを呼び出します。素数以外の数値が含まれています。その1つは、アプリケーションドメインの境界を越えています。 どちらの場合も、例外がスローされ、クライアントコードで正常に処理されます。

using System;
using System.Reflection;

class Example
{
   public static void Main()
   {
      int limit = 10000000;
      PrimeNumberGenerator primes = new PrimeNumberGenerator(limit);
      int start = 1000001;
      try
      {
         int[] values = primes.GetPrimesFrom(start);
         Console.WriteLine("There are {0} prime numbers from {1} to {2}",
                           start, limit);
      }
      catch (NotPrimeException e)
      {
         Console.WriteLine("{0} is not prime", e.NonPrime);
         Console.WriteLine(e);
         Console.WriteLine("--------");
      }

      AppDomain domain = AppDomain.CreateDomain("Domain2");
      PrimeNumberGenerator gen = (PrimeNumberGenerator)domain.CreateInstanceAndUnwrap(
                                        typeof(Example).Assembly.FullName,
                                        "PrimeNumberGenerator", true,
                                        BindingFlags.Default, null,
                                        new object[] { 1000000 }, null, null);
      try
      {
         start = 100;
         Console.WriteLine(gen.GetPrimesFrom(start));
      }
      catch (NotPrimeException e)
      {
         Console.WriteLine("{0} is not prime", e.NonPrime);
         Console.WriteLine(e);
         Console.WriteLine("--------");
      }
   }
}
Imports System.Reflection

Module Example
   Sub Main()
      Dim limit As Integer = 10000000
      Dim primes As New PrimeNumberGenerator(limit)
      Dim start As Integer = 1000001
      Try
         Dim values() As Integer = primes.GetPrimesFrom(start)
         Console.WriteLine("There are {0} prime numbers from {1} to {2}",
                           start, limit)
      Catch e As NotPrimeException
         Console.WriteLine("{0} is not prime", e.NonPrime)
         Console.WriteLine(e)
         Console.WriteLine("--------")
      End Try

      Dim domain As AppDomain = AppDomain.CreateDomain("Domain2")
      Dim gen As PrimeNumberGenerator = domain.CreateInstanceAndUnwrap(
                                        GetType(Example).Assembly.FullName,
                                        "PrimeNumberGenerator", True,
                                        BindingFlags.Default, Nothing,
                                        {1000000}, Nothing, Nothing)
      Try
         start = 100
         Console.WriteLine(gen.GetPrimesFrom(start))
      Catch e As NotPrimeException
         Console.WriteLine("{0} is not prime", e.NonPrime)
         Console.WriteLine(e)
         Console.WriteLine("--------")
      End Try
   End Sub
End Module
' The example displays the following output:
'      1000001 is not prime
'      NotPrimeException: 1000001 is not a prime number.
'         at PrimeNumberGenerator.GetPrimesFrom(Int32 prime)
'         at Example.Main()
'      --------
'      100 is not prime
'      NotPrimeException: 100 is not a prime number.
'         at PrimeNumberGenerator.GetPrimesFrom(Int32 prime)
'         at Example.Main()
'      --------

WindowsRuntime および .NET Framework 4.5.1

.net で Windows 8 用の Windows 8 ストアアプリを使用する場合、例外が非 .NET Framework スタックフレームを通じて伝達されると、通常、一部の例外情報が失われます。 .NET Framework 4.5.1 と Windows 8.1 以降、共通言語ランタイムは、 Exception 例外が非 .NET Framework スタックフレームで変更されていない限り、スローされた元のオブジェクトを引き続き使用します。

コンストラクター

Exception()

Exception クラスの新しいインスタンスを初期化します。

Exception(SerializationInfo, StreamingContext)

シリアル化したデータを使用して、Exception クラスの新しいインスタンスを初期化します。

Exception(String)

指定したエラー メッセージを使用して、Exception クラスの新しいインスタンスを初期化します。

Exception(String, Exception)

指定したエラー メッセージおよびこの例外の原因となった内部例外への参照を使用して、Exception クラスの新しいインスタンスを初期化します。

プロパティ

Data

例外に関する追加のユーザー定義情報を提供する、キーと値のペアのコレクションを取得します。

HelpLink

この例外に関連付けられているヘルプ ファイルへのリンクを取得または設定します。

HResult

特定の例外に割り当てられているコード化数値である HRESULT を取得または設定します。

InnerException

現在の例外の原因となる Exception インスタンスを取得します。

Message

現在の例外を説明するメッセージを取得します。

Source

エラーの原因となるアプリケーションまたはオブジェクトの名前を取得または設定します。

StackTrace

呼び出し履歴で直前のフレームの文字列形式を取得します。

TargetSite

現在の例外がスローされたメソッドを取得します。

メソッド

Equals(Object)

指定されたオブジェクトが現在のオブジェクトと等しいかどうかを判断します。

(継承元 Object)
GetBaseException()

派生クラスでオーバーライドされた場合、それ以後に発生する 1 つ以上の例外の根本原因である Exception を返します。

GetHashCode()

既定のハッシュ関数として機能します。

(継承元 Object)
GetObjectData(SerializationInfo, StreamingContext)

派生クラスでオーバーライドされた場合は、その例外に関する情報を使用して SerializationInfo を設定します。

GetType()

現在のインスタンスのランタイム型を取得します。

GetType()

現在のインスタンスの Type を取得します。

(継承元 Object)
MemberwiseClone()

現在の Object の簡易コピーを作成します。

(継承元 Object)
ToString()

現在の例外の文字列形式を作成して返します。

イベント

SerializeObjectState
互換性のために残されています。

例外がシリアル化され、例外に関するシリアル化されたデータを含む例外状態オブジェクトが作成されたときに発生します。

適用対象

こちらもご覧ください