C#应该抛出哪种异常?

12

我目前正在try catch中查找一个属性是否被正确地设置为应该是的布尔值,就像这样...

public void RunBusinessRule(MyCustomType customType)
{
    try
    {
       if (customType.CustomBoolProperty == true)
       {
            DoSomething(); 
       }
       else
       {
            throw new Exception("This is obviously false or possibly null lets throw up an error.");
       }
    }
    catch(Exception)
    {
        throw;
    }
}

现在,我遇到的问题是,我正在使用微软的源代码分析工具,它给我一个错误提示“CA2201: Microsoft.Usage: Object.RunBusinessRule(MyCustomType)引发了一个类型为'Exception'的异常,这是一个不够明确并且不应该由用户代码引发的异常类型。如果可能会抛出此异常实例,请使用其他异常类型。”

那么,我应该抛出什么样的异常才能足够符合微软的要求,适用于我的应用程序逻辑处理时所需的情况以及我希望“抛出”时的情况呢?

13个回答

18
ArgumentException
InvalidOperationException
FormatException

传入的参数不正确。

“InvalidOperationException”是指“在对象的当前状态下,方法调用无效时引发的异常”,即指类字段而非参数。 - brianary

13

创建一个继承 Exception 的自定义异常。例如:RuleViolationException


13

你是否真的需要抛出异常?

一个 false 的布尔值并不是一个异常情况。

编辑

我最初的回答可能有点简短,所以我来详细说明一下...

从你的示例中,实际的对象、属性和方法并不清楚。没有这些信息,很难说什么类型的异常(如果有)是适当的。

例如,我认为以下是完全有效使用异常的例子(而你的真实代码可能看起来像这样,但我们无法从你的示例中判断):

public void UpdateMyCustomType(MyCustomType customType)
{
    if (!customType.IsUpdateable)
        throw new InvalidOperationException("Object is not updateable.");

    // customType is updateable, so let's update it
}

但是在一般情况下,如果没有更多关于您的领域模型的了解,我会说这样的事情(一个假布尔值)并不是真正的异常情况。


4

2
这里的答案是不应该抛出任何异常。为什么要抛出异常,然后在下一秒钟再次捕获并重新抛出它呢?

1
我认为你应该避免在代码逻辑中使用异常。
我建议修改你的方法,将方法的结果作为bool类型返回,然后在调用方法时决定适当的方式向用户显示错误消息。
public bool RunBusinessRule(MyCustomType customType)
{
  try
    {
       if (customType.CustomBoolProperty == true)
       {
            DoSomething(); 
            return true;
       }

       return false;
    }
    catch(Exception)
    {
        throw;
    }
}

1

InvalidArgument异常可以,但更好的是一个ApplicationException。


3
Microsoft曾经推荐使用ApplicationException,但现在不再推荐了-请参见http://msdn.microsoft.com/en-us/library/seyhszts.aspx获取更多信息。 - LukeH
1
实际上,那篇文章说不要创建从ApplicationException派生的自定义异常;它并没有说不要抛出ApplicationException。 - ALEXintlsos
5
然而,Visual Studio代码分析显示ApplicationException“不够具体,不应该由用户代码引发”<叹气>。 - ALEXintlsos

1
稍微转个弯,你可以简化你的代码...
public void RunBusinessRule(MyCustomType customType)
{
    if (customType.CustomBoolProperty == false)
    {
        throw new Exception("This is obviously false or possibly null lets throw up an error.");
    }

    DoSomething(); 
}

关于要抛出的异常类型,您可以考虑使用ApplicationExceptionInvalidOperationException,或者您可以定义自己的异常类型。

就我个人而言,这样的简化总是让我感到困扰。就可读性而言,如果你要说“只有在布尔值为真时才执行此操作”,那么它应该成为if/then语句的一部分。这只是我的个人意见,但我总是更喜欢显式而不是隐式。 - Todd Friedlich

1

我知道这个问题涉及到抛出异常,但我认为在这里进行断言更加合适:

// Precondition: customType.CustomBoolProperty == true
System.Diagnostics.Debug.Assert(customType.CustomBoolProperty)
DoSomething();

1
其他答案对于快速解决问题是可以的,但是如果您在编译时知道某个方法不应该使用特定参数被调用,最好的方法是通过继承自定义类型来防止这种情况发生,仅在自定义布尔值为true时实例化它,现在您的方法看起来像这样。
public void RunBusinessRule(MyInheritedType inheritedObject)
{
    //No need for checks, this is always the right type.
    //As a matter of fact, RunBusinessRule might even belong to MyInheritedType.
}

这是SOLID中的I。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接