Exception.Data プロパティ

定義

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

public:
 virtual property System::Collections::IDictionary ^ Data { System::Collections::IDictionary ^ get(); };
public virtual System.Collections.IDictionary Data { get; }
member this.Data : System.Collections.IDictionary
Public Overridable ReadOnly Property Data As IDictionary

プロパティ値

IDictionary

IDictionary インターフェイスを実装し、ユーザー定義のキー/値ペアのコレクションを格納するオブジェクト。 既定値は空のコレクションです。

次の例では、プロパティを使用して情報を追加および取得する方法を Data 示します。

using namespace System;
using namespace System::Collections;

void NestedRunTest( bool displayDetails ); // forward declarations
void NestedRoutine1( bool displayDetails );
void NestedRoutine2( bool displayDetails );
void RunTest( bool displayDetails );

int main()
{
   Console::WriteLine("\nException with some extra information..." );
   RunTest(false);
   Console::WriteLine("\nException with all extra information..." );
   RunTest(true);
}

void RunTest( bool displayDetails )
{
   try
   {
      NestedRoutine1( displayDetails );
   }
   catch ( Exception^ e ) 
   {
      Console::WriteLine( "An exception was thrown." );
      Console::WriteLine( e->Message );
      if ( e->Data != nullptr )
      {
         Console::WriteLine( "  Extra details:" );

         for each (DictionaryEntry de in e->Data)
            Console::WriteLine("    Key: {0,-20}      Value: {1}", 
                               "'" + de.Key->ToString() + "'", de.Value);
      }
   }
}

void NestedRoutine1( bool displayDetails )
{
   try
   {
      NestedRoutine2( displayDetails );
   }
   catch ( Exception^ e ) 
   {
      e->Data[ "ExtraInfo" ] = "Information from NestedRoutine1.";
      e->Data->Add( "MoreExtraInfo", "More information from NestedRoutine1." );
      throw;
   }
}

void NestedRoutine2( bool displayDetails )
{
   Exception^ e = gcnew Exception( "This statement is the original exception message." );
   if ( displayDetails )
   {
      String^ s = "Information from NestedRoutine2.";
      int i = -903;
      DateTime dt = DateTime::Now;
      e->Data->Add( "stringInfo", s );
      e->Data[ "IntInfo" ] = i;
      e->Data[ "DateTimeInfo" ] = dt;
   }

   throw e;
}

/*
This example produces the following results:

Exception with some extra information...
An exception was thrown.
This statement is the original exception message.
  Extra details:
    The key is 'ExtraInfo' and the value is: Information from NestedRoutine1.
    The key is 'MoreExtraInfo' and the value is: More information from NestedRoutine1.

Exception with all extra information...
An exception was thrown.
This statement is the original exception message.
  Extra details:
    The key is 'stringInfo' and the value is: Information from NestedRoutine2.
    The key is 'IntInfo' and the value is: -903
    The key is 'DateTimeInfo' and the value is: 11/26/2002 2:12:58 PM
    The key is 'ExtraInfo' and the value is: Information from NestedRoutine1.
    The key is 'MoreExtraInfo' and the value is: More information from NestedRoutine1.
*/
// This example demonstrates the Exception.Data property.
using System;
using System.Collections;

class Sample
{
   public static void Main()
   {
      Console.WriteLine("\nException with some extra information...");
      RunTest(false);
      Console.WriteLine("\nException with all extra information...");
      RunTest(true);
   }

   public static void RunTest(bool displayDetails)
   {
      try {
         NestedRoutine1(displayDetails);
      }
      catch (Exception e) {
         Console.WriteLine("An exception was thrown.");
         Console.WriteLine(e.Message);
         if (e.Data.Count > 0) {
            Console.WriteLine("  Extra details:");
            foreach (DictionaryEntry de in e.Data)
               Console.WriteLine("    Key: {0,-20}      Value: {1}",
                                 "'" + de.Key.ToString() + "'", de.Value);
         }
      }
   }

   public static void NestedRoutine1(bool displayDetails)
   {
      try {
         NestedRoutine2(displayDetails);
      }
      catch (Exception e) {
         e.Data["ExtraInfo"] = "Information from NestedRoutine1.";
         e.Data.Add("MoreExtraInfo", "More information from NestedRoutine1.");
         throw;
      }
   }

   public static void NestedRoutine2(bool displayDetails)
   {
      Exception e = new Exception("This statement is the original exception message.");
      if (displayDetails) {
         string s = "Information from NestedRoutine2.";
         int i = -903;
         DateTime dt = DateTime.Now;
         e.Data.Add("stringInfo", s);
         e.Data["IntInfo"] = i;
         e.Data["DateTimeInfo"] = dt;
      }
      throw e;
   }
}
// The example displays the following output:
//    Exception with some extra information...
//    An exception was thrown.
//    This statement is the original exception message.
//      Extra details:
//        Key: 'ExtraInfo'               Value: Information from NestedRoutine1.
//        Key: 'MoreExtraInfo'           Value: More information from NestedRoutine1.
//
//    Exception with all extra information...
//    An exception was thrown.
//    This statement is the original exception message.
//      Extra details:
//        Key: 'stringInfo'              Value: Information from NestedRoutine2.
//        Key: 'IntInfo'                 Value: -903
//        Key: 'DateTimeInfo'            Value: 7/29/2013 10:50:13 AM
//        Key: 'ExtraInfo'               Value: Information from NestedRoutine1.
//        Key: 'MoreExtraInfo'           Value: More information from NestedRoutine1.
// This example demonstrates the Exception.Data property.
open System
open System.Collections

let nestedRoutine2 displayDetails =
    let e = Exception "This statement is the original exception message."
    if displayDetails then
        let s = "Information from nestedRoutine2."
        let i = -903
        let dt = DateTime.Now
        e.Data.Add("stringInfo", s)
        e.Data["IntInfo"] <- i
        e.Data["DateTimeInfo"] <- dt
    raise e

let nestedRoutine1 displayDetails =
    try
        nestedRoutine2 displayDetails
    with e ->
        e.Data["ExtraInfo"] <- "Information from nestedRoutine1."
        e.Data.Add("MoreExtraInfo", "More information from nestedRoutine1.")
        reraise ()

let runTest displayDetails =
    try
        nestedRoutine1 displayDetails
    with e ->
        printfn "An exception was thrown."
        printfn $"{e.Message}"
        if e.Data.Count > 0 then
            printfn "  Extra details:"
            for de in e.Data do
                let de = de :?> DictionaryEntry
                printfn $"""    Key: {"'" + de.Key.ToString() + "'",-20}      Value: {de.Value}"""

printfn "\nException with some extra information..."
runTest false
printfn "\nException with all extra information..."
runTest true

   
// The example displays the following output:
//    Exception with some extra information...
//    An exception was thrown.
//    This statement is the original exception message.
//      Extra details:
//        Key: 'ExtraInfo'               Value: Information from NestedRoutine1.
//        Key: 'MoreExtraInfo'           Value: More information from NestedRoutine1.
//
//    Exception with all extra information...
//    An exception was thrown.
//    This statement is the original exception message.
//      Extra details:
//        Key: 'stringInfo'              Value: Information from NestedRoutine2.
//        Key: 'IntInfo'                 Value: -903
//        Key: 'DateTimeInfo'            Value: 7/29/2013 10:50:13 AM
//        Key: 'ExtraInfo'               Value: Information from NestedRoutine1.
//        Key: 'MoreExtraInfo'           Value: More information from NestedRoutine1.
Imports System.Collections

Module Example
   Public Sub Main()
      Console.WriteLine()
      Console.WriteLine("Exception with some extra information...")
      RunTest(False)
      Console.WriteLine()
      Console.WriteLine("Exception with all extra information...")
      RunTest(True)
   End Sub

   Public Sub RunTest(displayDetails As Boolean)
      Try
         NestedRoutine1(displayDetails)
      Catch e As Exception
         Console.WriteLine("An exception was thrown.")
         Console.WriteLine(e.Message)
         If e.Data.Count > 0 Then
            Console.WriteLine("  Extra details:")
            For Each de As DictionaryEntry In e.Data
               Console.WriteLine("    Key: {0,-20}      Value: {1}",
                                 "'" + de.Key.ToString() + "'", de.Value)
            Next
         End If 
      End Try 
   End Sub 

   Public Sub NestedRoutine1(displayDetails As Boolean)
      Try
         NestedRoutine2(displayDetails)
      Catch e As Exception
         e.Data("ExtraInfo") = "Information from NestedRoutine1."
         e.Data.Add("MoreExtraInfo", "More information from NestedRoutine1.")
         Throw e
      End Try 
   End Sub

   Public Sub NestedRoutine2(displayDetails As Boolean)
      Dim e As New Exception("This statement is the original exception message.")
      If displayDetails Then 
         Dim s As String = "Information from NestedRoutine2." 
         Dim i As Integer = -903
         Dim dt As DateTime = DateTime.Now
         e.Data.Add("stringInfo", s)
         e.Data("IntInfo") = i
         e.Data("DateTimeInfo") = dt
      End If 
      Throw e
   End Sub 
End Module
' This example displays the following output: 
'    Exception with some extra information...
'    An exception was thrown.
'    This statement is the original exception message.
'      Extra details:
'        Key: 'ExtraInfo'               Value: Information from NestedRoutine1.
'        Key: 'MoreExtraInfo'           Value: More information from NestedRoutine1.
'    
'    Exception with all extra information...
'    An exception was thrown.
'    This statement is the original exception message.
'      Extra details:
'        Key: 'stringInfo'              Value: Information from NestedRoutine2.
'        Key: 'IntInfo'                 Value: -903
'        Key: 'DateTimeInfo'            Value: 7/29/2013 10:50:13 AM
'        Key: 'ExtraInfo'               Value: Information from NestedRoutine1.
'        Key: 'MoreExtraInfo'           Value: More information from NestedRoutine1.

注釈

System.Collections.IDictionaryプロパティによって返されるオブジェクトをData使用して、例外に関連する補足情報を格納および取得します。 この情報は、任意の数のユーザー定義キーと値のペアの形式です。 各キーと値のペアのキー コンポーネントは通常、識別文字列ですが、ペアの値コンポーネントは任意の種類のオブジェクトにすることができます。

キーと値のペアのセキュリティ

プロパティによって Data 返されるコレクションに格納されているキーと値のペアは安全ではありません。 アプリケーションが入れ子になった一連のルーチンを呼び出し、各ルーチンに例外ハンドラーが含まれている場合、結果の呼び出し履歴にはそれらの例外ハンドラーの階層が含まれます。 下位レベルのルーチンが例外をスローした場合、呼び出し履歴階層の上位レベルの例外ハンドラーは、他の例外ハンドラーによってコレクションに格納されているキーと値のペアを読み取りまたは変更できます。 つまり、キーと値のペアの情報が機密ではないことと、キーと値のペアの情報が破損している場合にアプリケーションが正しく動作することを保証する必要があります。

キーの競合

キーの競合は、異なる例外ハンドラーがキーと値のペアにアクセスするために同じキーを指定した場合に発生します。 重要な競合の結果として、下位レベルの例外ハンドラーが誤って上位レベルの例外ハンドラーと通信する可能性があり、この通信によって微妙なプログラム エラーが発生する可能性があるため、アプリケーションを開発するときは注意が必要です。 ただし、注意が必要な場合は、キーの競合を使用してアプリケーションを強化できます。

キーの競合の回避

キーと値のペアの一意のキーを生成する名前付け規則を採用して、キーの競合を回避します。 たとえば、名前付け規則では、アプリケーションのピリオド区切りの名前、ペアの補足情報を提供するメソッド、および一意の識別子で構成されるキーが生成される場合があります。

Products と Suppliers という名前の 2 つのアプリケーションに、それぞれ Sales という名前のメソッドがあるとします。 Products アプリケーションの Sales メソッドは、製品の ID 番号 (在庫保管単位または SKU) を提供します。 Suppliers アプリケーションの Sales メソッドは、サプライヤーの ID 番号 (SID) を提供します。 そのため、この例の名前付け規則では、キー "Products.Sales.SKU" と "Suppliers.Sales.SID" が生成されます。

キー競合の悪用

1 つ以上の特殊な事前に構成されたキーを使用して処理を制御することで、キーの競合を悪用します。 1 つのシナリオでは、呼び出し履歴階層の最上位レベルの例外ハンドラーが、下位レベルの例外ハンドラーによってスローされたすべての例外をキャッチするとします。 特殊なキーを持つキーと値のペアが存在する場合、高レベルの例外ハンドラーは、オブジェクト内 IDictionary の残りのキーと値のペアを何らかの非標準の方法で書式設定します。それ以外の場合、残りのキーと値のペアは何らかの通常の方法で書式設定されます。

次に、別のシナリオでは、呼び出し履歴階層の各レベルの例外ハンドラーが、次の下位レベルの例外ハンドラーによってスローされた例外をキャッチするとします。 さらに、各例外ハンドラーは、プロパティによって Data 返されるコレクションに、事前に構成されたキーのセットでアクセスできるキーと値のペアのセットが含まれていることを認識します。

各例外ハンドラーは、事前に配列されたキーのセットを使用して、対応するキーと値のペアの値コンポーネントを、その例外ハンドラーに固有の情報で更新します。 更新プロセスが完了すると、例外ハンドラーは次の上位レベルの例外ハンドラーに例外をスローします。 最後に、最上位レベルの例外ハンドラーはキーと値のペアにアクセスし、下位レベルのすべての例外ハンドラーから統合された更新情報を表示します。

適用対象

こちらもご覧ください