d7s*_*rai 3 .net exception-handling try-catch
我想我有类似"程序员的强迫症"的东西.我喜欢我的代码是美观和干净的,我希望它是"完美的"(正如在处理所有可能的情况时那样正确和漂亮).我经常发现自己花了很多时间一次又一次地走过同一个地方,看看我可以在哪里进行优化以及哪些方面可以做到万无一失.
因此,当涉及到尝试......捕获块时,我会对所包含的内容感到一些偏执.我的意思是,我在哪里绘制代码应该满足的代码?例如,进行文件处理.我应该把一个该死的文件操作放在一个try ... catch块中,万一有些事情可能发生(文件被应用程序外部某人/某些东西锁定,磁盘损坏等)?
有时它会让我的大脑感觉到可能有些东西(我甚至都不知道)可能会绊倒一些代码.
编辑:
我不是在谈论使用try ... catch来涵盖糟糕的编程,我在谈论操作和程序,否则实现得当,但依赖于我无法控制的其他因素 - 即使它们可能是模糊不清(这就是重点),只有在我没有预料到的极其"不幸"的情况下才会发生.
文件处理是一个明显的例子.当我倾向于让人感到紧张时,我就想知道在其他内置功能的幕后进行什么样的处理,以及它如何响应我的代码.
这是一个例子:
Dim serverUrl as String = My.Settings.ServerUrl
Run Code Online (Sandbox Code Playgroud)
那里有一个磁盘操作(从app.config读取).如果是在一个try ... catch块封闭?这就是我的意思,它在哪里结束.
害怕内存泄漏是另一回事.是否只有非托管代码才会构成威胁?我怎么知道什么是非托管代码?有清单吗?
更多编辑:
另一个我感到不自信的领域是在引擎盖下的某些地方有访问限制或政策.
当我阅读关于编程的文章和讨论时,我看到了很多解释,"好吧,你的问题是当你打电话给X时,.Net在内部试图访问某某,除非你的应用程序在上下文类型Y中运行,或者您具有权限Z,它将引发异常".这只会增加我的偏执 - 当涉及到建立防水异常处理时.因为我根本不知道语言/平台的所有内部运作,并且不知道在哪里看(不必花费我的生命来研究它).
我很乐意为此专门制作某种形式的纲要或简明的维基,这将概述需要特别关注的编程领域(文件处理等),示例场景,典型挑战和罪魁祸首(使用解决方案),最佳实践模型,编程模式,并且至少为像我这样的凡人提供了一套指导方针,遗憾的是,它并没有参与实际构建语言及其库.
所有这一切都在一个地方,而不是必须在语言参考或网上的随机文章中追踪分散的信息 - 在许多情况下我甚至不知道该寻找什么.
至于我当前的特定项目,它是在Windows服务的上下文中.没有UI,我正在研究的一个子任务是创建一个健壮的引导程序,可以优雅地处理所有问题场景.在这种情况下,所有关于日志记录 - 然后要么忽略异常(如果它足够微不足道) - 或者只是退出!如果在尝试登录时发生问题 - 那我该怎么办?刚退出 - 没有发生什么事情的痕迹?这个引导程序只记录它的启动(之后,主程序集 - 它是动态加载的 - 接管并记录它自己的东西,尽管有相同的挑战),并且这样做是为了一个简单的"bootstrap.log"文件.将它登录到EventLog会更好(或有价值的补充)吗?或者EventLog是另一个可能产生新问题世界的区域(同样,访问限制等等.事件日志是否也基于需要"尝试和捕获"的磁盘操作......?)
看到?偏执狂.
我应该把一个该死的文件操作放在一个try ... catch块中,万一有些事情可能发生(文件被应用程序外部某人/某些东西锁定,磁盘损坏等)?
一般来说,是的.
文件操作本质上是不安全的,当你使用它时,一切都会崩溃.考虑一下您正在读取存储在USB存储设备上的文件并且读取中间用户拉出USB记忆棒的情况.
这将引发异常,你需要防范这一点.在您提到的特定示例中也是如此.
另一方面,通常只需要处理此类错误的高级代码,而不是业务逻辑中的深层代码.通常可以让方法失败并因IO故障而传播异常.防止此异常导致应用程序崩溃,并通知用户出现问题,或重试或采取规避措施,这一点非常重要.
Ned Batchelder在2003年发表的一篇文章解释了代码的哪些部分应该防范异常,哪些不应该:
他将代码分为三层:
我会选择稍微不同的层:
无论如何,最低层应该将较低级API的异常转换为您的域.
中间层应该允许异常通过:业务层中没有异常处理.这也应该是您的大部分代码,这意味着您不需要在大多数代码中处理异常(但当然可能是此规则的例外).
并且上层应该捕获异常并对它们做出响应,或者以可读格式将它们呈现给用户.处理这种异常的一种好方法是安装全局异常处理程序,或者将GUI应用程序中的工作卸载到额外的线程(例如BackgroundWorker)中,并在线程死亡时捕获异常.
并非所有例外都需要以这种方式处理.例如,你不应该尝试处理StackOverflowException
(你不能!)或OutOfMemoryException
(你通常不能).
此类异常意味着代码或计算机存在严重错误,并且您的应用程序无法从故障中恢复.