C# System.Exception.Data属性
Exception类(实际上是任何异常)的数据属性几乎总是空的。抛出异常时,此字段是否有任何用处?或者它是否有一些我不知道的内部用途?关于它的用途,似乎已经足够清楚了(重点加上): 获取键/值对的集合,这些键/值对提供有关异常的其他用户定义信息 它为什么首先存在?我假设这与C# System.Exception.Data属性,c#,.net,exception,C#,.net,Exception,Exception类(实际上是任何异常)的数据属性几乎总是空的。抛出异常时,此字段是否有任何用处?或者它是否有一些我不知道的内部用途?关于它的用途,似乎已经足够清楚了(重点加上): 获取键/值对的集合,这些键/值对提供有关异常的其他用户定义信息 它为什么首先存在?我假设这与控件具有相同的原因。在.NET的早期(在每个Bob和Betty程序员都了解对象和继承之前),他们希望使API足够简单,以便每个人都能想出如何向事物添加额外数据 但是,创建从System.Exception派生的自定义异常的目的
控件
具有相同的原因。在.NET的早期(在每个Bob和Betty程序员都了解对象和继承之前),他们希望使API足够简单,以便每个人都能想出如何向事物添加额外数据
但是,创建从System.Exception
派生的自定义异常的目的不一定要包括额外的信息,而是使客户端能够将捕获的异常限制为只能处理的异常。如果他们知道如何处理代码可以抛出的一组已定义的异常,那么他们应该只能捕获这些异常,而不必捕获基本的System.Exception
类。您绝对不应该要求客户机代码捕获一个非特定的异常类并读取一个属性来确定它是什么类型的异常(以及它们是否能够处理它)
老实说,我以前从未用过这房子。我必须检查文件,甚至看它是否确实存在。但我认为它对于实现自定义异常日志记录最有用。您可以将许多重要信息嵌入到
数据
属性中(无论异常类的派生级别如何),然后将其传递给日志代码。反射器表明,它的内部使用在一些地方正是为了这个目的。您在这里提供的所有信息都能自动正确序列化,这也很好。这里的另一个注意事项是,当我继承异常并添加属性时,我要做的是使属性实际从数据字典中获取和设置,而不是从局部变量中获取和设置
[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);
}
}
在我看来,内部数据也可以从异常中获得,例如在日志记录时,因此无需转换为实际类型。使用新的
CallerMemberNameAttribute
更容易使用data
属性进行存储:
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;
}
}
公共类BetterException:异常
{
受保护的T GetValue([CallerMemberNameAttribute]字符串propertyName=”“)
{
返回(T)数据[propertyName];
}
受保护的void SetValue(T值,[CallerMemberNameAttribute]字符串propertyName=”“)
{
数据[propertyName]=值;
}
}
用法:
class MyException : BetterException
{
public MyException(string name)
{
Name = name;
}
public string Name
{
get { return GetValue<string>(); }
set { SetValue(value); }
}
}
MyException类:BetterException
{
公共MyException(字符串名称)
{
名称=名称;
}
公共字符串名
{
获取{return GetValue();}
set{SetValue(value);}
}
}
这一直是我感兴趣的事情。为什么会有这样的财产?子类化Exception
不是包含您自己数据的更好方法吗?我有一种感觉,Control.Tag
的可能重复主要是由于设计师(微软似乎非常喜欢)而存在的。据我所知,您需要跳过一些障碍,才能使自己的子类TextBox
在设计器中与基本类一样出色地显示出来。但很少使用GUI设计器设计异常。@Matti:我一直使用自定义控件。我不知道有这样的事情。您必须将控件添加到工具箱中,是的。但我不确定这与必须使用声明添加一个来使用在另一个名称空间中定义的类型有什么不同。(您还可以重新调整IDE,用同一项目中定义的控件自动填充工具箱。)结果与内置控件一样好,至少如果您继承自控件
或其子类之一。我使用Data属性跟踪有关错误的其他信息—通常是发生错误的方法的状态信息,因此当我将错误传递给更高级别的处理程序时,所有这些状态信息都将包含在日志中。在跟踪bug时,日志中的额外信息非常有用。这是一种奇妙的模式。我会更进一步,添加一个覆盖的ToString来自动包含数据属性。注意GetValue中的无效强制转换。数据字典是公共的和可变的。任何可以获取异常引用的人都可以在其中一个键后面放置不同的数据对象。e、 g.ex.Data[“Name”]=42代码>@StevenLiekens你是对的,事实上我不再使用这个了。关于异常,只有两件事是有用的:异常的名称和消息。剩下的你可以忘了。