【问题标题】:Which of the two exceptions was called?这两个异常中的哪一个被调用了?
【发布时间】:2011-02-20 11:00:07
【问题描述】:

如果我有一个可以在两个地方抛出 ArgumentException 的例程,比如...

if (Var1 == null)
{
    throw new ArgumentException ("Var1 is null, this cannot be!");
}

if (Val2  == null)
{
    throw new ArgumentException ("Var2 is null, this cannot be either!");
}

在我的调用过程中确定抛出两个异常中的哪一个的最佳方法是什么?

或者

我这样做的方式不对吗?

【问题讨论】:

    标签: c# .net asp.net exception-handling


    【解决方案1】:

    您的调用函数不应该关心是哪一行导致了异常。在任何一种情况下都会抛出ArgumentException,并且应该以相同的方式处理两者。

    【讨论】:

    • +1 这也很容易在调用方法之前检查。
    • 但是如果我想根据抛出的两个异常中的哪一个向用户显示特定消息?
    • 您可以使用异常本身的文本,也可以改为抛出ArgumentNullException
    【解决方案2】:

    将第二个参数中的变量名称(Val1、Val2 等)传递给 ArgumentException 构造函数。这将成为 ArgumentException.ParamName 属性。

    【讨论】:

      【解决方案3】:

      对于这种特定情况,您应该使用 ArgumentNullException 并正确填充它的 ParamName 属性,以便您知道为空的参数。

      ArgumentException 类也支持相同的属性,但您应该使用可用的最具体的异常类型。

      使用这些类型的异常时,在使用同时接受消息和参数名称的构造函数时也要小心。每种异常类型之间的顺序切换:

      throw new ArgumentException("message", "paramName");
      
      throw new ArgumentNullException("paramName", "message");
      

      【讨论】:

        【解决方案4】:
        try
                {
                    //code here
                }
                catch (ArgumentException ae)
                {
                    Console.WriteLine(ae.ToString());
                }
        

        控制台中的输出将告诉您输入的消息。

        【讨论】:

          【解决方案5】:

          使用构造函数ArgumentException(string, string)定义,哪个参数为null。

          if (Var1 == null) {
            throw new ArgumentException ("Var1 is null, this cannot be!","Var1");
          }
          
          if (Val2  == null){
            throw new ArgumentException ("Var2 is null, this cannot be either!","Var2");
          }
          

          【讨论】:

            【解决方案6】:

            嗯,特别是对于 ArgumentException,您有一个参数有问题:

            throw new ArgumentException("Var1 is null, this cannot be!", "Var1");
            

            在更一般的意义上,你通常会做一些事情,比如使用不同的(可能是自定义的)异常类型,然后调用代码可以有不同的 catch 块

            public class MyCustomException1 : ApplicationException {}
            public class MyCustomException2 : ApplicationException {}
            
            
            try
            {
             DoSomething();
            }
            catch(MyCustomException1 mce1)
            {
            }
            catch(MyCustomException2 mce2)
            {
            }
            catch(Exception ex)
            {
            }
            

            【讨论】:

            • 在这种情况下,ArgumentException 的第二个参数应该是一个字符串,即有问题的参数的名称。
            【解决方案7】:

            您应该问自己的更大问题是为什么?如果您试图从中排除某种逻辑,那么异常通常是一个不好的方法。

            相反,您应该有一个返回类型(或 out/ref 参数),该类型将使用某种标志/值进行设置,您可以从调用代码中检测到该标志/值,以确定错误是什么,并将您的逻辑排除在外.

            如果你坚持使用异常,那么在这种情况下,ArgumentNullException has a constructor that takes the name of the parameter and the exception message。您可以抛出异常,然后当您捕获异常时,访问ParamName property 以确定导致异常的参数的名称。

            【讨论】:

              【解决方案8】:

              当抛出ArgumentExceptions 时,您始终可以包含导致异常的参数的名称(它是another constructor)。当然我假设你真的想知道哪个是空的,在这种情况下,你应该使用ArgumentNullException

              【讨论】:

                【解决方案9】:

                如果这是一个测试用例,您想确保显示正确的异常消息,我知道 NUnit 有一个 ExpectedMessage 关键字到 ExpectedException 属性。否则,ArgumentNullExceptionArgumentNullException,您的应用程序应该对它们一视同仁。如果您想了解更多细节,请创建自己的异常类并使用它们。

                因此您可以测试以下内容:

                [ExpectedException(typeof(ArgumentNullException), ExpectedMessage="Var1 is null, this cannot be!"]
                public void TestCaseOne {
                    ...
                }
                
                [ExpectedException(typeof(ArgumentNullException), ExpectedMessage="Var2 is null, this cannot be either!"]
                public void TestCaseTwo {
                    ...
                }
                

                【讨论】:

                  【解决方案10】:

                  您确实没有提供足够的信息来回答您的问题。显而易见的答案是查看异常的消息,但我猜这不是您想要的。

                  如果能够以编程方式区分它们真的很重要,那么请使用另一个异常,或者至少使用当前异常构造函数的paramName 属性。这将为您提供更多相关信息。

                  但是,使用您自己的异常类型是保证您在特定情况下捕获异常的唯一方法。因为ArgumentException 是框架的一部分,所以你调用的其他东西可能会抛出它,这会导致你进入同一个catch 块。如果您创建自己的异常类型(一种用于两种情况或一种用于每种情况),这将为您提供一种处理特定错误的方法。当然,从您的示例来看,在调用函数开始之前检查 Val1Val2 是否为空似乎会更简单。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2019-12-08
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多