2011-04-30 12 views
28

La clase System.Exception (en realidad cualquier excepción) tiene la propiedad Data que casi siempre está vacía. Mientras arroja excepciones, ¿debería este campo ser de alguna utilidad? ¿O tiene algún uso interno del que no tengo conocimiento?Propiedad System.Exception.Data

+1

Esto es algo que siempre me ha intrigado. ¿Por qué hay tal propiedad? ¿No es una subclasificación de 'Excepción' una mejor forma de incluir sus propios datos? –

+1

posible duplicado de [Usando Exception.Data] (http://stackoverflow.com/questions/144957/using-exception-data) –

Respuesta

16

El documentation parece bastante claro en cuanto a su uso (énfasis añadido):

Obtiene una colección de pares clave/valor que proporcionan información adicional definida por el usuario sobre la excepción.

¿Por qué existe en primer lugar? Supongo que es la misma razón Control tiene un Tag property. En los primeros días de .NET (antes de que cada programador de Bob y Betty entendiera los objetos y la herencia) querían que la API fuera lo suficientemente simple para que todos pudieran encontrar la manera de agregar datos adicionales a las cosas.

Sin embargo, el punto de crear excepciones personalizadas que se derivan de System.Exception no es necesariamente para incluir información adicional, pero para que sea posible para el cliente para limitar las excepciones que capturan a solamente aquellos que pueden manejar. Si saben cómo manejar un conjunto de excepciones definidas que su código puede arrojar, deberían ser capaces de detectar solo esas excepciones, sin tener que atrapar la clase base System.Exception. Lo que definitivamente debería nunca es do es requerir el código del cliente para atrapar una clase de excepción no específica y leer una propiedad para determinar qué tipo de excepción es (y por lo tanto si pueden o no manejarla).

Honestamente, nunca he usado esta propiedad antes. Tuve que verificar la documentación para ver si realmente existía. Pero me imagino que es más útil para implementar el registro de excepciones personalizado. Puede incorporar mucha información importante en la propiedad Data (independientemente del nivel de derivación de la clase de excepción) y luego pasarla a su código de registro. El reflector indica que se usa internamente en un puñado de lugares para precisamente ese propósito. También es bueno que toda la información que proporciones aquí se serialice correctamente automáticamente.

+0

Tengo la sensación de que 'Control.Tag' sobre todo existe debido a los diseñadores (que Microsoft parece ser muy aficionado). Por lo que sé, necesitas saltar unos aros para que tu propio 'TextBox' subclasificado aparezca en un diseñador igual de bien que la clase básica.Sin embargo, las excepciones rara vez se diseñan utilizando un diseñador de GUI. –

+0

@Matti: uso controles personalizados todo el tiempo. No estoy al tanto de tales aros. Tienes que agregar los controles a la caja de herramientas, sí. Pero no estoy seguro de cómo es eso diferente de tener que agregar una declaración 'using' para usar tipos definidos en otro espacio de nombres. (También puede volver a configurar el IDE para rellenar automáticamente la caja de herramientas con los controles definidos en el mismo proyecto). El resultado es tan bueno como los controles incorporados, al menos si hereda de 'Control' o una de sus subclases. –

+2

Utilizo la propiedad de Datos para rastrear información adicional sobre el error; generalmente informo sobre el método en el que ocurre el error, de modo que cuando paso el error a manejadores de nivel superior, toda esa información de estado se incluirá en mis registros. Al rastrear errores, esa información adicional en los registros es muy útil. – Zarepheth

11

Otra nota aquí, lo que hago cuando heredo una excepción y agrego propiedades, es hacer que las propiedades realmente se obtengan y configuren del diccionario de datos, y no de las variables locales.

[Serializable] 
public class PacketParseException : Exception 
{ 
    public byte[] ByteData 
    { 
     get 
     { 
      return (byte[])this.Data["ByteData"]; 
     } 
    } 

    public PacketParseException(string message, byte[] data, Exception inner) : base(message, inner) 
    { 
     this.Data.Add("ByteData", data); 
    } 
} 

El modo de ver, a continuación, los datos internos se encuentra disponible a partir de una excepción, así, por ejemplo al iniciar la sesión, así que no hay necesidad de emitir a tipo real.

6

Con el nuevo CallerMemberNameAttribute es aún más fácil de usar la propiedad Data para el almacenamiento:

public class BetterException : Exception 
{ 
    protected T GetValue<T>([CallerMemberNameAttribute] string propertyName = "") 
    { 
     return (T)Data[propertyName]; 
    } 

    protected void SetValue<T>(T value, [CallerMemberNameAttribute] string propertyName = "") 
    { 
     Data[propertyName] = value; 
    } 
} 

Uso:

class MyException : BetterException 
{ 
    public MyException(string name) 
    { 
     Name = name; 
    } 

    public string Name 
    { 
     get { return GetValue<string>(); } 
     set { SetValue(value); } 
    } 
} 
+2

Este es un patrón fantástico. Daría un paso más y agregaría un ToString anulado para incluir automáticamente las propiedades de Datos. –