繁体   English   中英

我可以/应该使用异常对程序进行错误检查吗?

[英]Can I/Should I use exceptions to error check my program?

这里的主要示例是复制Word文档。 我的程序中包含以下代码行:

try
{
    File.Copy(docTemplatePath, docOutputPath, true);
}
catch (IOException e)
{
    MessageBox.Show(e.ToString());
}

现在,我正在尝试建立错误检查。 我想确保在尝试保存之前未在其他位置打开输出Word文档,因为否则会引发异常。

我看到的方式是引发异常,以警告我导致错误的默认功能无法正常工作的代码。 从这个意义上讲,我会很乐意捕获异常,阅读该异常以识别问题(在这种情况下,该文档当前处于锁定状态/在其他位置打开),因此显示了一个MessageBox来提醒用户要尝试的文档事实写入在其他位置打开的文件。

这样可以吗? 在我研究此过程的过程中,我看到了很多地方,这似乎是异常的设计目标,而其他地方似乎人们认为使用异常来做这样的事情,这与所有编程传统相悖,并且宁愿自己检查一下。

总体共识是什么?

谢谢

您应该使用Exception处理异常情况

那是; 有时会出现可预见的情况:用户输入的文件名可能不存在,因此,例如,在尝试加载文件之前,您的代码应检查File.Exists() (不依赖于异常)。

该文件已经被使用并且被其他东西锁定可能是一种例外情况。 可能是这样,所以可能就好了。

在.Net中,IMO应将异常用于托管的意外错误。

对我来说,抛出一个身份验证错误(例如错误的密码)异常是一个坏主意,但是使用它来管理数据库连接错误则是一个好主意。

因此,简而言之,我使用异常来管理不可预期的问题而不是业务问题。 进行所有业务问题的想法都是一种“过度”的面向对象方法,而不是它应用于的目的。

您的例子是IMO,这是使用异常的好方法的一个很好的例子。 在全球范围内,这只是围绕功能或特定任务的“大尝试”。

AFAIK异常用于处理开发人员无法控制的事情,例如硬件故障或网络断开或类似的情况,而开发人员可能不知道该问题,

恕我直言,最好在表达式int r = val/divider;检查divider的值int r = val/divider; 比检查DivideByZeroException

使用“异常”控制程序流“未完成”。 当您不希望整个应用程序崩溃时,它们仅应用于处理特殊情况。

也就是说,有时需要使用异常。 我相信.NET Framework中的int.TryParse和其他TryParse方法使用Exceptions,如果不起作用则捕获它们,然后返回false。

如果没有其他方法可以知道是否已打开Word文件,则我认为您可以使用Exception来执行此操作。 好消息是您捕获了特定的异常,因为其他情况可能会出错。 问题是IOException可能有另一个源(即,目标文件夹不可访问,等等)。 这不仅适用于您的示例,而且适用于所有(复杂)异常驱动的流。 我在上面给出的TryParse示例非常简单,因此在这里并没有太大的问题。

结论:请勿这样做,除非这是您唯一的方法。 然后,尝试使用单独的方法将其隔离。 这样,如果您找到更好的解决方案,则可以随时更改实现。 另外,请尝试捕获最具体的异常,并记住异常可能有多种来源。

如果例程可以通过正常返回来满足其合同,则应该这样做。 如果例程无法在不违反其合同的情况下正常返回,则应引发异常。 如果将例程的合同作为给定的合同,那么在决定例程是否应该抛出异常时,判断的空间就很小。 它应该根据上述简单规则返回或抛出。

地方判断进入方程式是在决定例​​程的合同应该是什么。 一个有用的模式是提供例程的“尝试”版本和“执行”版本。 如果“尝试”版本由于合理预期的问题而无法执行所请求的操作,则它将通过返回某种类型的错误值来指示该错误; 如果“执行”版本由于任何原因无法执行请求的操作,它将引发异常。

作为一个简单的示例,请考虑“ Integer.TryParse”和“ Integer.Parse”。 如果一个字符串可能不是有效数字,则可以调用Integer.TryParse。 Integer.TryParse将使用返回的标志来指示解析是否成功;否则,返回false。 无论解析成功与否,它都会很高兴地返回,并且调用方负责在尝试使用返回的值之前确保TryParse成功。 相比之下,Integer.Parse仅在成功解析数字后才返回。 如果该数字无效,则Integer.Parse将引发异常。 因此,调用代码可以使用Integer.Parse返回的值,而不必检查它是否成功; 如果Integer.Parse没有成功,则不会返回。 注意,在某些真正特殊的情况下(例如,如果不安全的代码使传入的String引用指向某种其他类型的对象),Integer.TryParse可能引发异常。 唯一的保证是它不会在合理预期的情况下抛出(例如,它传递的字符串如“ XYZ”而不是诸如“ 123”的字符串)。

对Try / Do模式的一个略微增强是使例程接受一个委托,如果出现问题,该委托将被调用。 在很多情况下,通过委托会太过分,通常很难预先确定委托应采用的参数,但是这种方法在由外部决定是混淆还是放弃的情况下可能是有利的。因素。 这样的情况出现在通信场景中,其中程序对通信故障的正确响应可能是发出一条消息,通知用户该程序有困难并允许用户按下“取消”,但让程序重试该操作。如果用户没有几次。 如果必须重试的操作只占要执行的全部操作的一小部分,则在主线上抛出异常将“永久地”放弃较大的操作,而在没有用户交互的情况下执行重试可能会迫使用户令人讨厌的长时间坐在电脑上,使计算机放弃用户可能知道不会成功的操作(例如,因为电池刚在与之通信的设备上耗尽了)。 使用回调委托可以提供最佳的用户界面体验,而无需将通信代码绑定到任何特定的用户界面实现。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM