我在The Pragmatic Programmer和其他一些文章(包括来自Joel Spolsky的文章)中读过,你应该只在例外案例中抛出异常。否则,您应该返回错误。
有时可能(例如,返回-1
,-0
或positive number
),但在其他情况下,这是不可能的。我的意思是,如果你要返回一个班级,你总是可以返回null
,但我认为这个想法是返回一些能够提醒来电者发生的事情。
如果我总是返回null
,我认为说:如果此方法返回null,则可能是因为A,B,C,D或E
那么,如何在C#中实现这一目标呢?
修改
在我发布这个问题后的几个小时,我在这里看到了另一个问题,问题本身就是关于发布的代码是不是一个好习惯。
我看到这是我在这里做的事情的另一种方式。这是链接:
答案 0 :(得分:12)
何时抛出异常的更好的规则是:
当您的方法无法执行其名称所表示的操作时抛出异常。
空值可用于表示您已经要求不存在的内容。任何其他错误情况都不应该返回。
规则“只在特殊情况下抛出异常”是无助的IMO,因为它没有给你基准来表明什么是异常和什么不是。这就像说“只吃可食用的食物。”
答案 1 :(得分:10)
通过使用数字,您直接与Microsoft推荐的Exceptions相矛盾。我发现,使整个主题神秘化的最佳信息来源是Jeffrey Richter's CLR via C# 3。另外,.NET Framework Guidelines本书值得阅读其关于例外的材料。
不要返回错误代码。例外是在框架中报告错误的主要方法。
您可以采用的一个解决方案是out
参数,它可以获得结果。然后,您的方法返回bool
,就像您在框架中遇到的很多TryParse
方法一样。
答案 2 :(得分:8)
要考虑的一个例子是int.TryParse
。它对解析的值使用out
参数,并使用bool
返回值表示成功或失败。如果情况合适,bool
可以用枚举或更复杂的对象替换。 (例如,数据验证可能会以真正保证收集故障的方式失败等。)
使用.NET 4的替代方法是Tuple
...所以int.TryParse
可以:
public static Tuple<int, bool> TryParse(string text)
下一种可能性是让对象封装整个结果,包括适当的失败模式。例如,如果失败,您可以向Task<T>
询问结果,状态和异常。
所有这些只适用于发生这种情况的错误。它并不表示错误,只是用户输入错误。我真的不喜欢喜欢返回错误代码 - 在.NET中,异常更加惯用。
答案 3 :(得分:1)
Microsoft已经记录了.NET中错误处理的最佳实践
http://msdn.microsoft.com/en-us/library/8ey5ey87(VS.71).aspx
我建议遵循这些准则,因为它是.NET的标准,与其他.NET开发人员的冲突要少得多。
(注意,我意识到我发布了一个较旧的链接,但建议仍然存在。)
我也意识到不同的平台在看待正确的错误处理方式上有所不同。这可能是一个主观问题,但我会坚持上面所说的 - 在.NET中开发时遵循.NET准则。
答案 4 :(得分:1)
您可能需要考虑遵循TryXXX
模式,并允许客户端考虑几个简单的重载。
// Exception
public void Connect(Options o);
// Error Code
public bool TryConnect(Options o, out Error e);
答案 5 :(得分:1)
这意味着返回此类值的每个方法调用都会引入至少一个选择点(或更多,取决于返回值的域),从而引入更多可能的代码执行路径。所有这些都必须经过测试。
然后,假设Method1()和Method2()的约定要么成功或抛出异常,那么这个代码有1个可能流过它。:
foo.Method(...) ;
bar.Method(...) ;
如果这些方法通过返回代码指示状态,那么它会很快变得非常混乱。只返回二进制值:
bool fooSuccess = foo.Method(...);
if ( fooSuccess )
{
bool barSuccess = bar.Method(...);
if ( barSuccess )
{
// The normal course of events -- do the usual thing
}
else
{
// deal with bar.Method() failure
}
}
else // foo.Method() failed
{
// deal with foo.Method() failure
}
返回状态代码而不是抛出异常
调用者应该在调用方法之前检查以确保事情是重要的(例如,检查文件是否存在。如果文件不存在,请不要尝试打开它。)
执行您方法的合同:
如果违反合同,则抛出异常。 如果发生任何意外情况,则抛出异常。
你的代码应该是严格的纪律。
答案 6 :(得分:0)
只有当我确定在其他开发人员使用代码时不会产生误解时,我才会返回null
引用或负索引值等值。像LINQ函数IEnumerable<T>.FirstOrDefault
之类的东西。 IEnumerable<T>.First
会为空集合抛出异常,因为它会返回第一个元素,而空集合是一个例外情况