1

假设您正在调用类似于以下的方法,您知道该方法只会引发 2 个异常之一:

public static void ExceptionDemo(string input)
{
    if (input == null)
        throw new ArgumentNullException("input");

    if (input.Contains(","))
        throw new ArgumentException("input cannot contain the comma character");

    // ...
    // ... Some really impressive code here
    // ...
}

执行此操作的方法的真实示例是Membership.GetUser (String)

您将使用以下哪项来调用方法并处理异常:

方法一(先检查输入参数)

public static void Example1(string input)
{
    // validate the input first and make sure that the exceptions could never occur
    // no [try/catch] required
    if (input != null && !input.Contains(","))
    {
        ExceptionDemo(input);
    }
    else
    {
        Console.WriteLine("input cannot be null or contain the comma character");
    }
}

方法 2(将调用包装在 try/catch 中)

public static void Example2(string input)
{
    // try catch block with no validation of the input
    try
    {
        ExceptionDemo(input);
    }
    catch (ArgumentNullException)
    {
        Console.WriteLine("input cannot be null");
    }
    catch (ArgumentException)
    {
        Console.WriteLine("input cannot contain the comma character");
    }
}

多年来,我已经教授了这两种方法,并且想知道这种情况下的一般最佳实践是什么。

更新 一些海报关注的是抛出异常的方法,而不是处理这些异常的方式,所以我提供了一个.Net Framework 方法的示例,它的行为方式相同(Membership.GetUser (String))所以,为了澄清我的问题,如果我们打电话给您,您将Membership.GetUser(input)如何处理可能的异常,方法 1、2 或其他方法?

谢谢

4

4 回答 4

1

这取决于,但一般来说,所提出的两种方法都不是好的。如前所述,在第一种情况下,您正在复制代码。在第二个中,您在没有实际做任何事情的情况下捕获异常 - 甚至没有重新抛出,只是吞下它。如果您只想记录它或显示一些消息,通常您应该使用AppDomain.UnhandledException实现一个全局处理程序/记录器并在那里执行;这样,您不必用不必要的 try/catch 块污染您的代码。

这里真正的问题是输入是否为空或包含“,”在您的特定情况下是否真的是一种异常行为 - 例如,如果这是一些 GUI 输入的字符串,那么这通常不会导致异常抛出(最终用户错误应该是预料之中的)并且应该被适当地处理(例如警告重新输入输入)。在这种情况下,使用if语句来验证输入是正确的方法。但是,如果输入为 null 或包含“,”是实际的异常行为(例如,表明某些东西损坏或丢失的 API 问题),那么抛出异常是可以的。在这种情况下,您可以简单地调用ExceptionDemo(input)而不使用 try/catch。如果你想对异常做一些实际的事情(例如以某种方式改变输入),那么使用 try/catch。

于 2013-10-04T09:19:05.517 回答
0

调用者不应该假设他们正在调用的代码。

您的第一个示例很糟糕,因为您正在复制代码:调用者执行几乎string.INOE()vs string == null)与被调用者相同的检查(直到它们中的任何一个更改)。

第二个例子非常糟糕,因为它忽略了抛出的异常并给出了自己的解释。

像往常一样:这取决于。如果您有一个适当分层的应用程序,其中方法调用位于您的 UI 层中,您确实希望捕获该方法抛出的异常:您希望向用户显示这些错误。

于 2013-10-04T08:59:39.307 回答
0

这取决于调用 ExceptionDemo 的次数以及暴露给谁。如果它被广泛使用,那么当您知道(并记录)ExceptionDemo 无论如何都会进行检查时,您不会希望在调用 ExceptionDemo 之前检查条件。

鉴于返回类型为 void,如果输入错误,将 ExceptionDemo 更改为无效怎么办?

(您是否注意到您在方法 1 中更严格 - 空字符串不是有效输入,但在方法 2 中却是)

于 2013-10-04T09:05:32.347 回答
0

我会推荐标准和通用结构如下:

public static void Operation(object input)
{
    try
    {
        ValidateInput(input);
        //Do Operation
    }
    catch (MySpecificException subSubExceptionType) //Catch most specific exceptions
    {

        //Log or process exception
        throw;
    }
    catch (MySpecificException subExceptionType) //Catch specific exception
    {
        //Log or process exception
    }
    catch (Exception exceptionType) //Catch most generic exception
    {

        //Log or process exception
    }
    finally
    {
        //Release the resources
    }
}

private static void ValidateInput(object input)
{
    if(input == null)
        throw new NoNullAllowedException();
    //Check if properties of input are as expected. If not as expected then throw specific exception with specific message
}
于 2013-10-04T10:41:14.413 回答