C# 是否有任何合理的理由忽略捕获的异常
哇,我刚刚从外包的开发人员那里得到了一个巨大的C#项目,在检查代码时,我的分析工具发现了一堆它认为不好的东西。其中一条更令人沮丧的消息是:C# 是否有任何合理的理由忽略捕获的异常,c#,exception,C#,Exception,哇,我刚刚从外包的开发人员那里得到了一个巨大的C#项目,在检查代码时,我的分析工具发现了一堆它认为不好的东西。其中一条更令人沮丧的消息是: Exceptions.DontSwallowErrorsCatchingNonspecificExceptionsRule : 2106 defects 开发人员向我保证,他们有充分的理由使用所有的空catch块,有时使用空catch块只是为了忽略无用的异常并防止应用程序崩溃。我觉得这是一个借口,完全是废话。我实际查找的一些示例是数据库调用,其中记录被
Exceptions.DontSwallowErrorsCatchingNonspecificExceptionsRule : 2106 defects
开发人员向我保证,他们有充分的理由使用所有的空catch块,有时使用空catch块只是为了忽略无用的异常并防止应用程序崩溃。我觉得这是一个借口,完全是废话。我实际查找的一些示例是数据库调用,其中记录被保存到数据库中,在这种情况下,如果忽略异常,用户将返回一个OK提示,认为一切正常,然后继续工作。事实上,他们的工作从未得救。我认为这绝对是最可怕的错误。在本例中,他们在使用空catch块进行尝试时抛出该代码是完全错误的。但我的问题是,“这在任何情况下都是可以接受的吗?”我想不是,但我知道我错了 我有时使用网页显示不强制的网络控件。如果失败,我不想阻止页面显示。非关键网络控制的一个例子是显示广告
但是,我会记录错误。我只是不重复它。它取决于框架。实现糟糕的框架实际上可能需要这样做。我回忆起VB6中的一次黑客攻击,当时无法确定集合是否包含元素。唯一的方法是尝试检索元素并接受错误。除非我计划对异常采取措施,否则我不会捕获异常。忽略它们并不能解决问题。在关键代码中,可能不是,因为程序的状态必须始终精确定义。就像您的数据库调用示例一样 当然,在非关键代码中,我们也会这样做(我们只是在消息框中显示捕获的异常并保持运行)。可能插件或模块出现故障,但主程序不受影响。可能是一个词法转换失败了,屏幕上出现了一个文本故障。无需停止该过程。是的,根据Maxim的帖子,在某些情况下它是可以接受的(不可避免的,必要的)。这并不意味着你一定要喜欢它。2106违规可能太多了,至少他们应该在catch块中添加一条注释,说明为什么可以接受这个异常 @达斯汀
向公共用户显示任何异常详细信息(堆栈跟踪、行号等)是不好的做法。您可能应该记录异常并显示一个通用错误。 < P>一个我认为可以接受的例子是在一个关键应用程序的一些非关键模块中(例如,在航天飞机导航系统的声音反馈模块中),用于不应该发生的异常,并且不能更干净地处理。p> 在这种情况下,您不希望让异常传播并导致整个应用程序失败(对不起,伙计们,没有更多的导航系统,我们的蜂鸣器模块崩溃,我们对此无能为力)
经过编辑,可以说在这些情况下,您至少希望将事件记录在某个地方 这真是件坏事 虽然有合理的理由可以忽略异常——如果在某种程度上是预期的,并且没有必要对此采取任何措施——但是,做2000次似乎只是想掩盖他们的异常
可以接受异常的示例可能是对事物的探测。。。您向某个设备或模块发送消息,但您不在乎它是否真的到达那里。尽管有一些合理的理由可以忽略异常;但是,通常只有特定的例外情况才可以安全地忽略。正如所指出的,您可能必须捕获并接受错误作为框架的一部分;正如所指出的,可能有一个框架生成的异常,您知道可以忽略它 但是,在这两种情况下,您可能知道异常类型,如果您知道异常类型,那么您应该拥有与以下类似的代码:
try {
// Do something that might generate an exception
} catch (System.InvalidCastException ex) {
// This exception is safe to ignore due to...
} catch (System.Exception ex) {
// Exception handling
}
在您的应用程序中,在某些情况下可能会出现类似的情况;但是,您给出的数据库保存即使在出现异常时也返回“OK”的示例不是一个很好的迹象。我认为,如果有一个空的catch块,您需要记录它为什么为空,以便下一个开发人员知道。例如,在server.transfer上,有时会引发web异常。我注意到了这一点,并评论说我们可以因为转接电话而忽略它 通常情况下,没有,事实上99%的病例没有,但是 也有例外。在我参与的一个项目中,我们使用第三方库来处理TWAIN设备。这是错误的,在某些硬件组合下会抛出空指针错误。然而,我们从未发现任何情况下,它在扫描文档之前没有真正扫描文档,因此捕获异常是完全合理的
因此,我认为如果是您的代码引发了异常,那么您应该始终检查它,但是如果您被第三方代码卡住,那么在某些情况下,您可能会被迫接受异常并继续前进。我的感觉是,任何空的Catch块都需要注释 可能忽略某些错误是有效的,但您需要记录您的原因 此外,您也不希望将其设置为通用的“catch(Exception e){}”
您应该只捕获预期的、已知可以安全忽略的特定错误类型。当涉及异常时,总会有异常。我认为最好的经验法则是,只有完全了解异常的含义及其可能的后果时,才可以忽略异常。对于一些孤立的m
public void testSomething(){
try{
fooThatThrowsAnException(parameterThatCausesTheException);
fail("The method didn't throw the exception that we expected it to");
} catch(SomeException e){
// do nothing, as we would expect this to happen, if the code works OK.
}
}
@Test(expected = SomeException.class)
public void testSomething(){
fooThatThrowsAnException(parameterThatCausesTheException);
fail("The method didn't throw the exception that we expected it to");
}
Connection con = DriverManager.getConnection(url, "***", "***");
try {
PreparedStatement pStmt = con.prepareStatement("your query here");
... // query the database and get the results
}
catch(ClassNotFoundException cnfe) {
// real exception handling goes here
}
catch(SQLException sqle) {
// real exception handling goes here
}
finally {
try {
con.close();
}
catch {
// What do you do here?
}
}
public FileStream OpenFile(string path)
{
FileStream f = null;
try
{
f = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
}
catch (FileNotFoundException)
{
}
return f;
}
public FileStream OpenFile(string path)
{
FileStream f = null;
FileInfo fi = new FileInfo(path);
if (fi.Exists)
{
f = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
}
return f;
}
catch
{
}
String foo="foobar";
byte[] foobytes;
try
{
foobytes=foo.getBytes("UTF-8");
}
catch (UnsupportedEncodingException uee)
{
// This is guaranteed by the Java Language Specification not to occur,
// since every Java implementation is required to support UTF-8.
}
...
catch (UnsupportedEncodingException uee)
{
// This is guaranteed by the Java Language Specification not to occur,
// since every Java implementation is required to support UTF-8.
uee.printStackTrace();
}