我的自定义异常是否应该继承与它们类似的异常,或者只是从Exception继承?

时间:2009-06-23 13:09:28

标签: c# exception

我在我的应用程序中创建了一些自定义异常。

如果我有一个在测试参数状态后抛出的异常,或者我有一个在测试int在适当范围内后抛出的异常,我的异常是否会继承ArgumentException和IndexOutOfRangeException,或者它们是否应该继承异常?

10 个答案:

答案 0 :(得分:11)

由于继承用于指定要捕获的异常,因此您应该在做出决定时尊重这一点。

想一个带有附加信息的IOException,或ArgumentOutOfRangeException或ArgumentNullException以外的ArgumentException。

答案 1 :(得分:7)

假设您确实需要一个自定义异常,我会从Exception中继承最像您正在寻找的内容,而不仅仅是Exception。

尽管如此,我发现,在大多数情况下,使用正确的措辞,Exception消息通常足以创建一个全新的异常。

例如throw new IntOutOfProperRangeException();如何与throw new ArgumentOutOfRangeException("The int value was too large?");

显着不同

答案 2 :(得分:4)

我认为创建一个新的Exception类型总是更安全。如果您需要更改其处理方式,则可以更轻松地找到您正在或可能正在处理它的情况。找到MyException要比找到ArgumentOutOfRangeException的特定情况容易得多。您似乎能够在异常中提供一些额外的信息,并且创建异常并不是太多工作。

此外,我倾向于继承像MyBaseException这样的基础应用程序类,并确保为异常添加XML注释。

答案 3 :(得分:2)

我只是好奇,你为什么不实际使用已经存在的异常?听起来这些异常正是您所需要的,为什么反对使用它们?

答案 4 :(得分:2)

就个人而言,如果我有一个索引器并且索引值超出范围,那么我只是抛出现有的IndexOutOfRangeException,我不会麻烦从它继承。

如果您只讨论相似但不完全相同的异常,那么请看一下框架中提供的模式。它看起来并不合理,继承描述了一种“是一种”的关系。

答案 5 :(得分:1)

如果您不需要向异常添加任何其他数据,那么我只使用像IndexOutOfRangeException这样的本机.NET异常。

但是,如果你需要将一些与你的异常相关联的东西,你原本不能使用IndexOutOfRangeException,那么我将继承它。这里的好处是您可以捕获新的自定义异常类型或IndexOutOfRangeException。当然,如果您捕获基本类型,则不会有额外的属性等。

答案 6 :(得分:1)

恕我直言,从另一个例外继承是没有问题的。它使该例外的目的更加清晰。但请确保适用于ParentException的所有内容也适用于您创建的ChildException。否则,您最终可能会使用"Square extends Rectangle" problem ...

答案 7 :(得分:0)

我几乎总是使用IllegalArgumentException(nulls和/或超出范围的值)和IllegalStateException用于不比IOException,SQLException,Null更具体的任何东西......

答案 8 :(得分:0)

如果您只使用通用Exception,则永远无法捕获应用程序自定义的特定异常。如果您只是使用

try 
{
}
catch (Exception ex)
{
}

您将捕获每个异常而无法过滤特定错误。

我创建自定义异常的另一个原因是处理可能由于多种原因而发生的特定于应用程序的异常。这允许意味着抛出自定义异常,但自定义与异常关联的消息。它还为我的特定应用程序提供了另一级别的错误处理。

例如,我有一个适用于皮带传动系统尺寸的工程应用。该DLL也可供其他人使用。我有一个应用程序异常,当选择中发生错误时抛出该异常。出错的原因可能有很多(驱动速度无效,马力要求不正确等)。由于失败的原因有很多,因此自定义应用程序例外允许我提供失败的具体细节。

这也允许我向用户记录方法调用将抛出他们需要处理的特定于应用程序的异常。

如果继承Exception类,请确保在基类中实现具有消息,消息+内部异常和序列化异常的构造函数。

这是我的一个例子。

/// <summary>
/// Drive error exception class. Thrown when a drive selection error has occured.
/// </summary>
[Serializable]
public class DriveException : ApplicationException
{
    /// <summary>
    /// Default constructor.
    /// </summary>
    public DriveException()
    {
    }
    /// <summary>
    /// Constructor used with a message.
    /// </summary>
    /// <param name="message">String message of exception.</param>
    public DriveException(string message)
        : base(message)
    {
    }
    /// <summary>
    /// Constructor used with a message and an inner exception.
    /// </summary>
    /// <param name="message">String message of exception.</param>
    /// <param name="inner">Reference to inner exception.</param>
    public DriveException(string message, Exception inner)
        : base(message, inner)
    {
    }
    /// <summary>
    /// Constructor used in serializing the data.
    /// </summary>
    /// <param name="info">Data stored to serialize/de-serialize</param>
    /// <param name="context">Defines the source/destinantion of the straeam.</param>
    public DriveException(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
    }
}

答案 9 :(得分:0)

我认为这完全取决于您是否希望将ArgumentNotInPersitableState异常作为ArgumentOutOfRange捕获。如果有这样一个catch块(或者如果你正在编写一个框架,其他人可能会使用它),那么你应该继承相关的异常类型。