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 возвращаемой свойством, не защищены. Если приложение вызывает вложенный ряд подпрограмм и каждая подпрограмма содержит обработчики исключений, результирующий стек вызовов содержит иерархию этих обработчиков исключений. Если подпрограмма нижнего уровня создает исключение, любой обработчик исключений верхнего уровня в иерархии стека вызовов может считывать и /или изменять пары "ключ-значение", хранящиеся в коллекции любым другим обработчиком исключений. Это означает, что информация в парах "ключ-значение" не является конфиденциальной и что приложение будет работать правильно, если информация в парах "ключ-значение" повреждена.

Ключевые конфликты

Конфликт ключей возникает, когда разные обработчики исключений указывают один и тот же ключ для доступа к паре "ключ-значение". Используйте осторожность при разработке приложения, поскольку следствием конфликта ключей является то, что обработчики исключений более низкого уровня могут случайно взаимодействовать с обработчиками исключений более высокого уровня, и это взаимодействие может привести к незначительным ошибкам программы. Однако если вы осторожны, вы можете использовать ключевые конфликты для улучшения приложения.

Предотвращение ключевых конфликтов

Избегайте конфликтов ключей, применяя соглашение об именовании, чтобы создать уникальные ключи для пар "ключ—значение". Например, соглашение об именовании может дать ключ, состоящий из имени приложения с разделителями периода, метода, предоставляющего дополнительные сведения для пары, и уникальный идентификатор.

Предположим, что два приложения с именами "Продукты и поставщики" имеют метод Sales. Метод Sales в приложении Products предоставляет идентификационный номер (единицу хранения запасов или номер SKU) продукта. Метод Sales в приложении "Поставщики" предоставляет идентификационный номер или идентификатор безопасности поставщика. Следовательно, соглашение об именовании для этого примера дает ключи Products.Sales.SKU и "Suppliers.Sales.SID".

Использование конфликтов ключей

Конфликты ключей эксплойтов с помощью одного или нескольких специальных предварительно отпорядоченных ключей для управления обработкой. Предположим, в одном сценарии обработчик исключений верхнего уровня в иерархии стека вызовов перехватывает все исключения, создаваемые обработчиками исключений нижнего уровня. Если существует пара "ключ-значение" с специальным ключом, обработчик исключений высокого уровня форматирует оставшиеся пары "ключ-значение" в IDictionary объекте в некотором нестандартном порядке; в противном случае остальные пары "ключ-значение" форматируются обычным образом.

Предположим, что в другом сценарии обработчик исключений на каждом уровне иерархии стека вызовов перехватывает исключение, вызванное следующим обработчиком исключений нижнего уровня. Кроме того, каждый обработчик исключений знает коллекцию, возвращаемую свойством Data , содержит набор пар "ключ-значение", к которым можно получить доступ с помощью предварительно отсортированного набора ключей.

Каждый обработчик исключений использует предварительно заданный набор ключей для обновления компонента значения соответствующей пары "ключ-значение" с информацией, уникальной для этого обработчика исключений. После завершения процесса обновления обработчик исключений создает исключение для следующего обработчика исключений более высокого уровня. Наконец, обработчик исключений верхнего уровня обращается к парам "ключ-значение" и отображает консолидированные сведения об обновлении всех обработчиков исключений нижнего уровня.

Применяется к

См. также раздел