【问题标题】:C# what kind of exception should I raise?C# 我应该提出什么样的异常?
【发布时间】:2009-02-06 17:58:38
【问题描述】:

我目前正在尝试查找某个属性是否已正确设置为应该是这样的 bool 值...

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;
    }
}

现在为我抛出此错误的处理是我正在使用 Microsoft 的源分析,它给了我一个错误,指出“CA2201:Microsoft.Usage:Object.RunBusinessRule(MyCustomType) 创建了一个‘Exception’类型的异常,一个异常类型不够具体,不应由用户代码引发。如果可能引发此异常实例,请使用不同的异常类型。

Soooo 我应该抛出什么异常,这对于 Microsoft 来说已经足够具体了......,对于抛出关于我自己的应用程序逻辑处理的错误以及何时我想“抛出”的情况。

【问题讨论】:

    标签: c#


    【解决方案1】:
    ArgumentException
    InvalidOperationException
    FormatException
    

    传入的参数不好。

    【讨论】:

    • InvalidOperationException是“当方法调用对于对象的当前状态无效时抛出的异常。”,即类字段,而不是参数。
    【解决方案2】:

    你应该抛出异常吗?

    具有错误的布尔值并不完全是一种例外情况。

    编辑

    我最初的答案有点简洁,所以我会详细说明...

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

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

    public void UpdateMyCustomType(MyCustomType customType)
    {
        if (!customType.IsUpdateable)
            throw new InvalidOperationException("Object is not updateable.");
    
        // customType is updateable, so let's update it
    }
    

    但在一般情况下,如果不了解您的域模型的更多信息,我会说这样的事情(一个错误的布尔值)并不是真正的例外。

    【讨论】:

      【解决方案3】:

      创建您自己的扩展Exception 的异常。例如:RuleViolationException

      【讨论】:

        【解决方案4】:

        ArgumentException 可能吗?

        InvalidOperationException 也可以申请。

        【讨论】:

          【解决方案5】:

          这里的答案是你不应该抛出任何异常。为什么要抛出异常只是为了在一秒钟内再次捕获并重新抛出它?

          【讨论】:

            【解决方案6】:

            稍有不慎,但您可以稍微简化代码...

            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(); 
            }
            

            至于抛出的异常类型,可以考虑ApplicationException或InvalidOperationException,也可以自己定义异常类型。

            【讨论】:

            • 就我个人而言,这样的简化总是让我感到困扰。就可读性而言,我认为如果您说“仅当 bool 为真时才这样做”,那么它应该是 if/then 语句的一部分。这只是我个人的意见,但我总是宁愿看到明确而不是暗示。
            【解决方案7】:

            我知道一个问题是关于抛出异常,但我认为在这里做一个断言会更合适:

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

            【讨论】:

              【解决方案8】:

              InvalidArgument 异常很好,但更好的是 ApplicationException。

              【讨论】:

              • Microsoft 曾经推荐 ApplicationException,但现在不再推荐了 - 请参阅 msdn.microsoft.com/en-us/library/seyhszts.aspx 了解更多信息。
              • 实际上,该帖子说不要创建自己的从 ApplicationException 派生的异常;它并没有说不要抛出 ApplicationException。
              • Edit 但是,Visual Studio 代码分析表明 ApplicationException “不够具体,不应由用户代码引发”。
              【解决方案9】:

              其他答案可以快速解决,但理想情况下,如果您在编译时知道不应该使用某些参数调用某个方法,您可以通过继承您的自定义类型来防止这种情况发生,仅在该类型时实例化它custom bool 为真,现在你的方法看起来像。

              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中的我。

              【讨论】:

                【解决方案10】:

                我认为您应该避免代码逻辑异常。

                我建议修改您的方法以将您的方法的结果作为bool 类型返回,然后您可以决定在调用该方法时向用户显示错误消息的适当方式:

                public bool RunBusinessRule(MyCustomType customType)
                {
                  try
                    {
                       if (customType.CustomBoolProperty == true)
                       {
                            DoSomething(); 
                            return true;
                       }
                
                       return false;
                    }
                    catch(Exception)
                    {
                        throw;
                    }
                }
                

                【讨论】:

                  【解决方案11】:

                  通过扩展 System.Exception 来创建您自己的自定义异常并抛出它。如果你愿意,你可以变得更疯狂,拥有一整棵异常类型树。

                  【讨论】:

                    【解决方案12】:

                    您可以创建一个仅用于您的业务逻辑验证的自定义ValidationException。或者您可以为每种类型的验证错误创建一个单独的验证异常,尽管这可能是过载。

                    【讨论】:

                      【解决方案13】:

                      并不是你真正想要的,但有很多人已经给出了我同意的答案,但你也应该避免只使用 catch(Exception ex)。

                      最好先尝试捕获可能的特定异常,如果需要,捕获通用异常。例如:

                      try{
                         MyMethod(obj);
                      }catch (NullReferenceException ne){
                         //do something
                      }
                      catch(UnauthorizedAccessException uae){
                         //do something else
                      }
                      catch(System.IO.IOException ioe){
                         //do something else
                      }
                      catch(Exception){
                         //do something else
                      }
                      

                      【讨论】:

                      • 他也将获得带有此代码的 CA2201,因为 NullReferenceException 和 Exception 至少不应该被运行时以外的其他东西使用。
                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2014-02-15
                      • 1970-01-01
                      • 2010-11-18
                      • 2015-05-12
                      • 2011-05-06
                      • 1970-01-01
                      相关资源
                      最近更新 更多