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 的應用程式,每個應用程式都有一個名為 Sales 的方法。 Products 應用程式中的 Sales 方法會提供識別碼 (產品的庫存單位或 SKU) 。 供應商應用程式中的 Sales 方法提供供應商的識別碼或 SID。 因此,此範例的命名慣例會產生金鑰 「Products.Sales.SKU」 和 「Suppliers.Sales.SID」。

惡意探索金鑰衝突

利用有一或多個特殊預先排列的索引鍵來控制處理,以惡意探索金鑰衝突。 假設在一個案例中,呼叫堆疊階層中的最高層級例外狀況處理常式會攔截較低層級例外狀況處理常式擲回的所有例外狀況。 如果具有特殊索引鍵的索引鍵/值組存在,高階例外狀況處理常式會以一些非標準的方式格式化物件中的 IDictionary 剩餘索引鍵/值組;否則,其餘索引鍵/值組會以某種一般方式格式化。

現在假設在另一個案例中,呼叫堆疊階層每個層級的例外狀況處理常式會攔截下一個較低層級例外狀況處理常式擲回的例外狀況。 此外,每個例外狀況處理常式都知道 屬性所 Data 傳回的集合包含一組索引鍵/值組,可使用預先排列的索引鍵集來存取。

每個例外狀況處理常式都會使用預先排列的索引鍵集來更新對應索引鍵/值組的值元件,以及該例外狀況處理常式唯一的資訊。 更新程式完成之後,例外狀況處理常式會將例外狀況擲回至下一個較高層級的例外狀況處理常式。 最後,最高層級例外狀況處理常式會存取索引鍵/值組,並顯示來自所有較低層級例外狀況處理常式的合併更新資訊。

適用於

另請參閱