可以/我是否可以使用异常来检查我的程序?

时间:2011-12-07 12:29:02

标签: c# exception exception-handling

这里的主要例子是复制word文档。我的程序中有这些代码行:

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

现在我正在尝试构建错误检查。我想确保在我尝试保存之前输出的Word文档没有在别处打开,因为否则会抛出异常。

我看到它的方式是抛出异常以警告我导致代码的默认功能无法按预期工作的错误。在这个意义上,我会很自如地捕获异常,阅读它以辨别问题(在这种情况下,文档当前在其他地方被锁定/打开)并因此显示MessageBox以警告用户文档他们的事实'我试图写一个在别处打开的文件。

这样可以吗?在我看到这个过程中,我看到很多地方看起来这就是异常的目的,而其他地方人们似乎认为使用异常来做这样的事情是对所有编程传统和我宁愿自己检查一下。

总体共识是什么?

由于

5 个答案:

答案 0 :(得分:2)

您应该使用例外来处理异常事件

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

该文件已被使用并被其他锁定,可能是一种特殊情况;它可能是,所以这可能就好了。

答案 1 :(得分:1)

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

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

所以,简而言之,我使用例外来管理不可预见的问题,而不是业务问题。以异常方式处理每个业务问题的想法更多的是“过度”面向对象的方法,而不是它应该用于什么。

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

答案 2 :(得分:0)

AFAIK Exceptions旨在处理开发人员控制的内容,如硬件故障或断开连接的网络或类似的情况,开发人员可能不知道问题,

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

答案 3 :(得分:0)

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

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

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

结论:不要这样做,除非这是你能做到的唯一方法。然后,尝试以单独的方法隔离它。这样,如果您找到更好的解决方案,您可以随时更改您的实施。此外,尝试捕获最具体的异常,并记住异常可以有多个来源。

答案 4 :(得分:0)

如果例程能够通过正常返回来满足其合同,则应该这样做。如果例程在没有违反合同的情况下无法正常返回,则应抛出异常。如果一个例程的契约被视为一个给定的,那么在判断例程是否应该抛出异常时,判断的空间真的不大。它应该基于上述简单规则返回或抛出。

地方判断进入等式是决定例行合同应该是什么。一个有用的模式是提供例程的“Try”版本和“Do”版本;如果“Try”版本由于合理预期的问题而无法执行请求的操作,则表示通过返回某种类型的错误值;如果“Do”版本因任何原因无法执行请求的操作,则会抛出异常。

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

Try / Do模式的一个小改进是让例程接受一个委托,如果出现问题将被调用。在许多情况下,通过一名代表将是过度的,而且通常很难事先决定代表应该采取什么参数,但是这种方法在以下情况下可能是有利的:在是否可以由外界决定是否混淆或放弃因素。这种情况出现在通信场景中,其中程序对通信打嗝的正确响应可能是通知用户程序有困难并允许用户点击“取消”但是让程序重试操作的消息。如果用户没有,则几次。如果必须重试的操作只是要执行的整个操作的一小部分,则向主线抛出异常将“永久”地放弃更大的操作,而在没有用户交互的情况下执行重试可能会迫使用户非常渴望计算机放弃用户可能知道不会成功的操作(例如,因为电池刚刚在他正在与之通信的设备上死亡)。使用回调委托可以获得最佳的用户界面体验,而无需将通信代码与任何特定的用户界面实现联系起来。