假设您正在调用类似于以下的方法,您知道它只会抛出以下两种情况之一:
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)
您将使用以下哪种方法来调用方法并处理异常:
方法1(首先检查输入参数)
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或其他什么?
由于
答案 0 :(得分:1)
这取决于,但一般来说,两种方法都不是很好。如前所述,在第一种情况下,您正在复制代码。在第二种情况下,你正在捕捉异常,而没有真正做任何事情 - 甚至没有重新抛出,只是吞下它。如果您只想记录它或显示一些消息,通常您应该使用AppDomain.UnhandledException实现全局处理程序/记录器并在那里执行;这样,您就不必使用不必要的try / catch块污染您的代码。
这里真正的问题是输入是否为空或包含','在您的特定情况下是否真的是一种例外行为 - 例如如果这是一些GUI输入的字符串,那么这通常不应该导致异常抛出(应该预期最终用户错误)并且应该适当地处理(例如,警告重新输入输入)。在这种情况下,使用if
语句来验证输入是正确的方法。但是,如果输入为null或包含','是一个实际的异常行为(例如,指示某些内容已损坏或丢失的API问题),则抛出异常即可。在这种情况下,您可以简单地调用ExceptionDemo(input)
而不使用try / catch。如果你想真正对异常做一些事情(例如以某种方式改变输入),那么使用try / catch。
答案 1 :(得分:0)
来电者不应该对他们正在呼叫的代码采取任何行动。
你的第一个例子很糟糕,因为你正在复制代码:调用者执行几乎(string.INOE()
vs string == null
)与被调用者相同的检查(直到他们改变了。)
第二个例子非常糟糕,因为它忽略了抛出的异常,并给出了自己的解释。
像往常一样:这取决于。如果你有一个正确分层的应用程序,方法调用在你的UI层,你做想要捕获方法抛出的异常:你将要向用户显示这些错误。答案 2 :(得分:0)
这取决于ExceptionDemo被调用的次数以及它被暴露的次数。如果它被广泛使用,那么在调用ExceptionDemo之前你不想检查条件,当你知道(并记录)ExceptionDemo无论如何都要进行检查时。
鉴于返回类型为void,如果输入错误,将ExceptionDemo更改为无效?
(您是否注意到在方法1中更严格 - 空字符串不是有效输入,但在方法2中它是)
答案 3 :(得分: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
}