C# - 为什么要实现标准的异常构造函数?

时间:2009-05-31 07:10:32

标签: c# exception coding-style

从MSDN,代码分析警告CA1032:

Exception types must implement the following constructors: 
  • public NewException()
  • public NewException(string)
  • public NewException(string, Exception)
  • protected or private NewException(SerializationInfo, StreamingContext)
我理解序列化构造函数背后的目的,但是“要求”其他构造函数背后的理由是什么?为什么我不应该只定义对我的异常使用有意义的构造函数?如果我不想在不传递消息的情况下抛出MyException,我该怎么定义无参数构造函数呢?如果我希望MyException有一个int属性并且我只想要初始化该属性的构造函数怎么办?

6 个答案:

答案 0 :(得分:11)

这是警告,不是要求。它基本上是principle of least surprise。提供所有4个使得习惯于“常规”C#例外的人更容易使用你的。如果您有充分理由忽略该指南,请执行此操作。但它会破坏某些使用场景,并使你的课程变得不那么直观。

答案 1 :(得分:11)

你已经得到了一些好的答案。我只想补充说,提供这些额外的构造函数并不一定需要大量的编码。由于它们已经在基类中实现,因此您可以简单地让它们完成工作:

public class MyCustomException : Exception
{
    public MyCustomException() : base() { }
    public MyCustomException(string message) : base(message) { }
    public MyCustomException(string message, Exception innerException) : base(message, innerException) { }
    // and so on...
}

因此,您只需要实现代码,其中异常的行为与基类的行为不同。

答案 2 :(得分:3)

实现标准异常构造函数允许人们以标准,熟悉的方式使用您的异常,该方法内置于所有现有的.NET异常中。前三个可以是可选的,如果由于某种原因你不想使用其中一个(虽然为什么你会想要我无法理解。)但是,最后一个是反序列化构造函数,如果你愿意您的异常在任何类型的分布式环境(.NET Remoting,ASP.NET Web服务,WCF等)中都受支持,那么它非常重要。

如果没有反序列化构造函数和[Serializable]属性,您的异常将无法在分布式环境中运行,并可能导致其他问题。鉴于这一点,以及熟悉C#开发人员的熟悉程度,最好至少实现4个标准异常构造函数,并使用[Serializable]标记您的异常。

答案 3 :(得分:2)

无参数和序列化构造函数由通用“异常路由”代码使用,该代码需要在域之间移动异常(例如,在服务和客户端之间通过互联网)。

采用另一个Exception的那个是可以通过InnerException属性链接所有异常。

最后,有一个带有消息字符串的字符串,这有助于使用合理一致的异常。

答案 4 :(得分:0)

为什么?因为。 (由于其他答案,异常路由需要使用无参数构造函数。)

我在同一地方,并且我不想在没有错误代码参数的情况下意外构造异常。所以这就是我所做的:

public class MyException : ArgumentException
{
    [Obsolete("Use a constructor that takes an ErrorCode instead")]
    public MyException() { }

    [Obsolete("Use a constructor that takes an ErrorCode instead")]
    public MyException(string message) : base(message) { }

    [Obsolete("Use a constructor that takes an ErrorCode instead")]
    public MyException(string message, Exception innerException) : base(message, innerException) { }

    public MyException(ErrorCode errorCode, string message) : base(message) { /* use error code */ }

    public MyException(ErrorCode errorCode, string message, Exception innerException) : base(message, innerException) { /* use error code */ }

    protected MyException(SerializationInfo info, StreamingContext context) : base(info, context)
    {
        if (info != null)
        {
            // error code stuff
        }
    }

    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        base.GetObjectData(info, context);
        if (info != null)
        {
            // error code stuff
        }
    }
}

答案 5 :(得分:-1)

嗯,采用内部异常的构造函数非常有必要使自定义异常正常使用。没有它,如果有人发现了你的异常,他们就无法在保留你原来的异常(及其携带的信息,如堆栈跟踪)的情况下触发更具描述性或适当的异常。