在C#中我如何定义自己的异常?

55 c# exception

在C#中我如何定义自己的异常?

Fre*_*els 68

创建自己的异常的准则(在您的类应该从异常继承的事实旁边)

  • 通过添加[Serializable]属性确保该类是可序列化的
  • 提供异常使用的公共构造函数:

    MyException ();
    
    MyException (string message);
    
    MyException (string message, Exception innerException);
    
    Run Code Online (Sandbox Code Playgroud)

所以,理想情况下,您的自定义Exception应该至少看起来像这样:

[Serializable]
public class MyException : Exception
{
    public MyException ()
    {}

    public MyException (string message) 
        : base(message)
    {}

    public MyException (string message, Exception innerException)
        : base (message, innerException)
    {}    
}
Run Code Online (Sandbox Code Playgroud)

关于你是否应该继承Exception或者ApplicationException:FxCop有一个规则,说你应该避免继承ApplicationException:

CA1058:Microsoft.Design:
更改"MyException"的基本类型,以便它不再扩展"ApplicationException".此基本异常类型不为框架类提供任何其他值.改为扩展'System.Exception'或现有的未密封异常类型.除非在为整个异常类创建catch处理程序时具有特定值,否则不要创建新的异常基类型.

有关此规则,请参阅MSDN上的页面.


Jus*_*ner 38


看起来我已经开始了一场Exception sublcassing battle.根据您遵循的Microsoft Best Practices指南,您可以继承System.Exception或System.ApplicationException.有一篇很好的(但是很旧的)博客文章试图消除混乱.我现在将保留我的Exception示例,但您可以阅读帖子并根据您的需要进行选择:

http://weblogs.asp.net/erobillard/archive/2004/05/10/129134.aspx

不再有战斗了!感谢Frederik指出FxCop规则CA1058,该规则指出您的异常应该继承System.Exception而不是System.ApplicationException:

CA1058:类型不应扩展某些基类型


定义一个继承自Exception的新类(我已经包含了一些构造函数......但你不必拥有它们):

using System;
using System.Runtime.Serialization;

[Serializable]
public class MyException : Exception
{
    // Constructors
    public MyException(string message) 
        : base(message) 
    { }

    // Ensure Exception is Serializable
    protected MyException(SerializationInfo info, StreamingContext ctxt) 
        : base(info, ctxt)
    { }
}
Run Code Online (Sandbox Code Playgroud)

在你的代码中的其他地方抛出:

throw new MyException("My message here!");
Run Code Online (Sandbox Code Playgroud)

编辑

更新了更改以确保Serializable Exception.详细信息可以在这里找到:

Winterdom博客存档 - 使异常类可序列化

如果向Exception类添加自定义属性,请密切关注有关需要采取的步骤的部分.

感谢伊戈尔给我打电话!

  • @Justin Niessner:如果你希望能够在AppDomains中抛出它,你必须使你的自定义异常可序列化 (2认同)
  • @Gabe Moothart:“您可以避免与自定义属性和序列化相关的麻烦”——只有当您的自定义属性“自动”可序列化时,即 CLR 知道如何序列化它 (2认同)
  • MS 在关于您应该从哪种类型继承自定义异常的指导方针中并不冲突。在.NET2.0之前,他们建议继承ApplicationException。从.NET2.0开始,他们建议从Exception继承。甚至还有 FxCop 规则强制执行这一点。(参见我对这个问题的回答) (2认同)
  • 顺便说一句,VS 的 IntelliSense 中有一个构造函数的片段。只需编写“Exception”并按两次 Tab 键即可。它具有此答案中的构造函数所具有的功能,并且还具有更多功能。 (2认同)

Wil*_*den 13

界定:

public class SomeException : Exception
{
    // Add your own constructors and properties here.
}
Run Code Online (Sandbox Code Playgroud)

投掷:

throw new SomeException();
Run Code Online (Sandbox Code Playgroud)


Jps*_*psy 9

来自微软的.NET Core 3.0 文档

定义您自己的异常类:

  1. 定义一个继承自Exception的类。如有必要,定义您的类所需的任何唯一成员以提供有关异常的附加信息。例如,ArgumentException 类包含一个 ParamName 属性,该属性指定其参数导致异常的参数名称,而 RegexMatchTimeoutException 属性包含一个 MatchTimeout 属性,该属性指示超时间隔。

  2. 如有必要,覆盖您想要更改或修改其功能的任何继承成员。请注意,大多数现有的 Exception 派生类不会重写继承成员的行为。

  3. 确定您的自定义异常对象是否可序列化。序列化使您能够保存有关异常的信息,并允许远程处理上下文中的服务器和客户端代理共享异常信息。要使异常对象可序列化,请使用 SerializedAttribute 属性对其进行标记。

  4. 定义异常类的构造函数。通常,异常类具有以下一个或多个构造函数:

  • Exception(),它使用默认值来初始化新异常对象的属性。

  • Exception(String),用指定的错误消息初始化一个新的异常对象。

  • Exception(String, Exception),使用指定的错误消息和内部异常初始化一个新的异常对象。

  • Exception(SerializationInfo, StreamingContext),它是一个受保护的构造函数,用于从序列化数据初始化一个新的异常对象。如果您选择使异常对象可序列化,则应该实现此构造函数。

例子:

using System;
using System.Runtime.Serialization;

[Serializable()]
public class NotPrimeException : Exception
{
   private int _notAPrime;
   public int NotAPrime { get { return _notAPrime; } }

   protected NotPrimeException() : base()
   { }

   public NotPrimeException(int value) : base(String.Format("{0} is not a prime number.", value))
   {
      _notAPrime = value;
   }

   public NotPrimeException(int value, string message) : base(message)
   {
      _notAPrime = value;
   }

   public NotPrimeException(int value, string message, Exception innerException) : base(message, innerException)
   {
      _notAPrime = value;
   }

   protected NotPrimeException(SerializationInfo info, StreamingContext context) : base(info, context)
   { }
}
Run Code Online (Sandbox Code Playgroud)

投掷中的用法:

throw new NotPrimeException(prime, "This is not a prime number."));
Run Code Online (Sandbox Code Playgroud)

try/catch 中的用法:

try
{
   ...
}
catch (NotPrimeException e)
{
   Console.WriteLine( "{0} is not prime", e.NotAPrime );
}
Run Code Online (Sandbox Code Playgroud)