Exception.Data 属性

定义

获取提供有关异常的其他用户定义信息的键/值对集合。Gets a collection of key/value pairs that provide additional user-defined information about the exception.

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 接口并包含用户定义的键/值对的集合。An object that implements the IDictionary interface and contains a collection of user-defined key/value pairs. 默认值为空集合。The default is an empty collection.

示例

下面的示例演示如何使用Data属性添加和检索信息。The following example demonstrates how to add and retrieve information using the Data property.

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. 
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补充信息。Use the System.Collections.IDictionary object returned by the Data property to store and retrieve supplementary information relevant to the exception. 此信息采用任意数量的用户定义的键/值对的形式。The information is in the form of an arbitrary number of user-defined key/value pairs. 每个键/值对的关键组件通常为标识字符串,而值对的值部分可以是任何类型的对象。The key component of each key/value pair is typically an identifying string, whereas the value component of the pair can be any type of object.

键/值对安全性Key/Value Pair Security

存储在由Data属性返回的集合中的键/值对是不安全的。The key/value pairs stored in the collection returned by the Data property are not secure. 如果你的应用程序调用一系列嵌套例程,并且每个例程包含异常处理程序,则生成的调用堆栈包含这些异常处理程序的层次结构。If your application calls a nested series of routines, and each routine contains exception handlers, the resulting call stack contains a hierarchy of those exception handlers. 如果较低级别例程引发异常,则调用堆栈层次结构中的任何高级异常处理程序都可以读取和/或修改任何其他异常处理程序存储在集合中的键/值对。If a lower-level routine throws an exception, any upper-level exception handler in the call stack hierarchy can read and/or modify the key/value pairs stored in the collection by any other exception handler. 这意味着,在键/值对中的信息已损坏的情况下,必须确保键/值对中的信息不是机密信息,并且应用程序将正常运行。This means you must guarantee that the information in the key/value pairs is not confidential and that your application will operate correctly if the information in the key/value pairs is corrupted.

键冲突Key Conflicts

当不同的异常处理程序指定访问键/值对所用的相同键时,会发生键冲突。A key conflict occurs when different exception handlers specify the same key to access a key/value pair. 开发应用程序时要格外小心,因为键冲突的后果在于,较低级别的异常处理程序可能会意外地与较高级别的异常处理程序通信,这种通信可能会导致微妙的程序错误。Use caution when developing your application because the consequence of a key conflict is that lower-level exception handlers can inadvertently communicate with higher-level exception handlers, and this communication might cause subtle program errors. 但是,如果你小心,可以使用密钥冲突来增强你的应用程序。However, if you are cautious you can use key conflicts to enhance your application.

避免密钥冲突Avoiding Key Conflicts

通过采用命名约定为键/值对生成唯一键,避免键冲突。Avoid key conflicts by adopting a naming convention to generate unique keys for key/value pairs. 例如,命名约定可能产生一个键,其中包含应用程序的句点分隔的名称、提供对的补充信息的方法以及唯一标识符。For example, a naming convention might yield a key that consists of the period-delimited name of your application, the method that provides supplementary information for the pair, and a unique identifier.

假设两个应用程序(名为产品和供应商)都有一个名为 Sales 的方法。Suppose two applications, named Products and Suppliers, each has a method named Sales. "产品" 应用程序中的 "销售" 方法提供产品的标识号(库存单位或 SKU)。The Sales method in the Products application provides the identification number (the stock keeping unit or SKU) of a product. 供应商应用程序的 Sales 方法提供供应商的标识号或 SID。The Sales method in the Suppliers application provides the identification number, or SID, of a supplier. 因此,此示例的命名约定会生成密钥 "Products. 销售 SKU" 和 "供应商名称"。Consequently, the naming convention for this example yields the keys, "Products.Sales.SKU" and "Suppliers.Sales.SID".

利用关键冲突Exploiting Key Conflicts

使用一个或多个特殊的预先安排密钥来控制处理,从而利用密钥冲突。Exploit key conflicts by using the presence of one or more special, prearranged keys to control processing. 假设在一种情况下,调用堆栈层次结构中最高级别的异常处理程序将捕获由较低级别的异常处理程序引发的所有异常。Suppose, in one scenario, the highest level exception handler in the call stack hierarchy catches all exceptions thrown by lower-level exception handlers. 如果存在具有特殊键的键/值对,则高级异常处理程序将以某种非标准的方式设置IDictionary对象中剩余的键/值对的格式; 否则,将以某种正常方式设置其余键/值对的格式。If a key/value pair with a special key exists, the high-level exception handler formats the remaining key/value pairs in the IDictionary object in some nonstandard way; otherwise, the remaining key/value pairs are formatted in some normal manner.

现在,假设在另一种情况下,调用堆栈层次结构每个级别的异常处理程序都将捕获下一个较低级别的异常处理程序引发的异常。Now suppose, in another scenario, the exception handler at each level of the call stack hierarchy catches the exception thrown by the next lower-level exception handler. 此外,每个异常处理程序知道Data属性返回的集合包含一组键/值对,这些键/值对可使用一组预先安排的键进行访问。In addition, each exception handler knows the collection returned by the Data property contains a set of key/value pairs that can be accessed with a prearranged set of keys.

每个异常处理程序使用预先安排的键集来使用该异常处理程序的唯一信息更新相应键/值对的值部分。Each exception handler uses the prearranged set of keys to update the value component of the corresponding key/value pair with information unique to that exception handler. 更新过程完成后,异常处理程序会将异常引发到下一个更高级别的异常处理程序。After the update process is complete, the exception handler throws the exception to the next higher-level exception handler. 最后,最高级别的异常处理程序访问键/值对,并显示来自所有较低级别的异常处理程序的合并的更新信息。Finally, the highest level exception handler accesses the key/value pairs and displays the consolidated update information from all the lower-level exception handlers.

适用于

另请参阅