Yip*_*Yay 7 language-agnostic exception-handling exception
我最近被告知我滥用异常来控制应用程序中的流量,所以我这是我试图以某种方式澄清情况.
在我看来,一个方法应该在遇到情况时抛出异常,这种情况无法在内部处理或者可能由调用方更好地处理.
那么 - 是否存在任何特定的规则集,可用于在开发应用程序时回答以下问题:
什么时候应该抛出一个异常,什么时候应该编写具有强大的nothrow保证的代码,这可能只是返回 bool
表示成功或失败?
我应该尝试最小化情况的数量,当方法抛出异常时,或者相反,它应该最大化以在处理这些情况时提供灵活性吗?
我应该坚持在开发我的应用程序时使用的框架/运行时设置的异常抛出约定,还是应该包装所有这些调用,以便它们匹配我自己的异常抛出策略?
我还建议使用错误代码进行错误处理,这似乎非常有效,但从语法的角度来看很丑陋(同样,当使用它们时,开发人员失去了为方法指定输出的能力).你怎么看待这件事?
实施例为第三个问题(I用的I/O架构和遇到以下情况):
所描述的框架不使用异常来处理错误,但其他代码确实使用它们.我是否应该将所有可能的失败包裹起来
'???'
并在这种情况下抛出异常?或者我应该将方法的签名更改为bool PrepareTheResultingOutputPath
仅指示操作是否成功?
public void PrepareTheResultingOutputFile(
String templateFilePath, String outputFilePath)
{
if (!File.Exists(templateFilePath))
// ???
if (!Directory.MakePath(outputFilePath))
// ???
if (File.Exists(outputFilePath))
if (!File.Remove(outputFilePath))
// ???
if (!File.Copy(templateFilePath, outputFilePath)
// ???
}
Run Code Online (Sandbox Code Playgroud)
另一个例子 - 即使.NET Framework
不遵循一些严格的异常抛出策略.一些方法被记录为抛出10多种不同的异常类型,包括普通的异常类型NullArgumentException
,但其中一些只是返回bool
以指示操作的成功或失败.
谢谢!
异常的问题在于它们本质上是美化的 goto,能够展开程序的调用堆栈。因此,如果您“使用异常进行流量控制”,那么您可能将它们用作 goto 而不是异常条件的指示。这正是例外的要点,也是其名称的原因:它们应该仅在例外情况下使用。因此,除非一个方法被设计为不抛出异常(.NET 就是一个例子int.TryParse
),否则可以抛出异常来响应异常情况。
与 Java 相比,C# 的优点在于,在 C# 中,您基本上可以通过返回元组类型或使用 out 参数来返回两个或多个值。因此,返回错误代码作为方法的主要返回值并没有太多丑陋之处,因为您可以使用 out 参数来完成其余的操作。例如,调用的常见范例int.TryParse
是
string s = /* Read a string from somewhere */;
int n;
if (int.TryParse(s, out n))
{
// Use n somehow
}
else
{
// Tell the user that they entered a wrong number
}
Run Code Online (Sandbox Code Playgroud)
现在回答你的第三个问题,这似乎是最重要的。参考您的示例代码,您询问是否应该返回bool
来指示成功/失败,或者是否应该使用异常来指示失败。不过,还有第三种选择。您可以定义一个枚举来告诉方法如何失败,并将该类型的值返回给调用者。然后,调用者有一个广泛的选择:调用者不必使用一堆 try/catch 语句,也不必使用 if 来了解方法如何失败,但可以选择编写其中之一
if (PrepareTheResultingOutputFile(templateFilePath, outputFilePath) == Status.Success)
// Do something
else
// It failed!
Run Code Online (Sandbox Code Playgroud)
或者
switch (PrepareTheResultingOutputFile(templateFilePath, outputFilePath))
{
case Status.Success:
// Do something
break;
case Status.FileNotPresent:
// Do something else
break;
case Status.CannotMakePath:
// Do something else
break;
// And so on
default:
// Some other reason for failure
break;
}
Run Code Online (Sandbox Code Playgroud)
您可以在此处和此处找到有关此问题的更多信息,特别是在我强烈推荐的Joel Spolsky 的帖子中。
归档时间: |
|
查看次数: |
1943 次 |
最近记录: |