除非我确定不会有任何错误,否则我总是会因为从不采取行动来防止异常情况.我学会了用C编程,这是真正做事的唯一方法.
使用C#我经常看到更多的被动编程 - 尝试做某事并处理异常.对我来说,这似乎是使用异常作为控制语句.我最初看到这几次,我认为这是不好的做法.但是在过去的几个月里,我已经看到了这一切,只是不得不怀疑 - 这是接受/有效还是只是流行病?
更新:为了澄清一点,我看到的大多数异常处理都是这样的
try { //open file } catch { //message box for file not found }
甚至更糟
try { //open xml //modify xml (100+ lines of code) } catch { //message for 'unspecified error' }
我知道有时候异常处理非常好用(例如数据库连接),但我指的是使用异常来代替更"传统"的控制.我之所以问这个是因为我觉得这种编程风格使用异常作为拐杖而不是恢复方法,并且想知道这是否是我在C#世界中必须学会期待的东西.
像往常一样,答案是"它取决于",但我一般都赞同"快速失败"的理念.
我更喜欢使用try/finally(sans catch),除非我能真正做一些有用的事情来从特定代码块中的异常中恢复.抓住每一个可能的例外是不值得的.通常,快速失败比无声失败更可取.
另一方面,如果您知道如何从特定异常中恢复,那么是的,那就去做吧.
假设您有一个文件传输库.如果传输因超时或网络故障而中断,它可能会抛出异常.那是合理的.如果图书馆无声地失败,你会感到恼火; 检查返回代码更容易出错,并且不一定更具可读性.但也许您有一个业务规则,用于将一堆文件发送到服务器,您应该在放弃并要求用户干预之前至少尝试3次传输文件.在这种情况下,业务逻辑应该处理异常,尝试恢复,然后在自动解决方案失败时做任何应该做的事情(提醒用户,安排稍后的尝试,或其他什么).
如果您找到执行此操作的代码:
try { // do something that could throw // ... } catch {} //swallow the exception
要么:
catch { return null; }
那可能已经破了.当然,有时您调用的代码可能会抛出您真正不关心的异常.但我经常看到人们这样做只是为了让他们不必"处理"上游的异常; 这种做法使事情变得更难调试.
有些人认为允许例外将责任链串联起来是不好的,因为你只是"希望"上游某人"奇迹般地"知道该怎么做.那些人错了.上游代码通常是唯一可以知道该做什么的地方.
偶尔,我会尝试/捕获并抛出一个不同的,更合适的异常.但是,如果可能的话,保护条款会更好.例如.if (argument==null) throw new ArgumentNullException();
比允许NullReferenceException传播调用堆栈更好,因为它更清楚出错了.
应该记录"应该永远不会发生"或"我不知道可能发生"的某些条件(例如,参见jboss日志记录),但是在它们关闭应用程序之前可以吞下它们,至少在某些情况下是这样.
ETA:可能会破坏特定的异常,然后显示一般的,模糊的错误消息.对于上面的第二个例子,这对我来说听起来很糟糕.对于你的第一个,"找不到文件",这可能更合理(如果你真的抓住了那个特定的例外,而不仅仅是"一切"),除非你有更好的方法在其他地方处理这个条件.模态消息框对我来说通常是一个糟糕的"交互设计气味",但这主要是不重要的.
在某些情况下,您被迫被动反应:检查和操作并不总是有效.
访问磁盘上的文件:磁盘是否正常工作?文件存在吗?我可以获得对该文件的读取权限吗?
访问数据库:服务器是否接受连接?我的证书好吗?数据库对象是否存在?名称/ type的列是否正确?
所有这些都可以在检查和操作之间改变.