我刚刚看到一个关于try-catch的问题,哪些人(包括Jon Skeet)认为空catch块是一个非常糟糕的主意?为什么呢?在任何情况下,空接点都不是错误的设计决策吗?
我的意思是,例如,有时你想从某个地方(webservice,数据库)获得一些额外的信息,你真的不关心你是否会得到这个信息。所以你试着获取它,如果发生了什么,没关系,我只会添加一个“catch (Exception ignored){}”,仅此而已
我刚刚看到一个关于try-catch的问题,哪些人(包括Jon Skeet)认为空catch块是一个非常糟糕的主意?为什么呢?在任何情况下,空接点都不是错误的设计决策吗?
我的意思是,例如,有时你想从某个地方(webservice,数据库)获得一些额外的信息,你真的不关心你是否会得到这个信息。所以你试着获取它,如果发生了什么,没关系,我只会添加一个“catch (Exception ignored){}”,仅此而已
当前回答
在某些情况下,您可能会使用它们,但它们应该非常不频繁。我可能会使用它的情况包括:
异常日志记录;根据上下文的不同,您可能希望发布一个未处理的异常或消息。 循环技术情况,如渲染或声音处理或列表框回调,行为本身将演示问题,抛出异常将只是阻碍,记录异常可能只会导致1000个“失败到XXX”消息。 不能失败的程序,尽管它们至少应该记录一些东西。
对于大多数winforms应用程序,我发现对于每个用户输入都有一个try语句就足够了。我使用以下方法:(AlertBox只是一个快速的消息框。显示包装)
public static bool TryAction(Action pAction)
{
try { pAction(); return true; }
catch (Exception exception)
{
LogException(exception);
return false;
}
}
public static bool TryActionQuietly(Action pAction)
{
try { pAction(); return true; }
catch(Exception exception)
{
LogExceptionQuietly(exception);
return false;
}
}
public static void LogException(Exception pException)
{
try
{
AlertBox(pException, true);
LogExceptionQuietly(pException);
}
catch { }
}
public static void LogExceptionQuietly(Exception pException)
{
try { Debug.WriteLine("Exception: {0}", pException.Message); } catch { }
}
然后每个事件处理程序都可以这样做:
private void mCloseToolStripMenuItem_Click(object pSender, EventArgs pEventArgs)
{
EditorDefines.TryAction(Dispose);
}
or
private void MainForm_Paint(object pSender, PaintEventArgs pEventArgs)
{
EditorDefines.TryActionQuietly(() => Render(pEventArgs));
}
理论上,您可以使用tryactionsilent,它可能更适合呈现调用,这样异常就不会生成无穷无尽的消息。
其他回答
一般来说,这是一个坏主意,因为这是一个真正罕见的情况,即失败(更普遍的情况是例外情况)没有得到任何回应。最重要的是,空捕获块是使用异常引擎进行错误检查的人使用的常用工具,他们应该先发制人地进行错误检查。
说它总是不好是不真实的……这种情况很少发生。在某些情况下,您不关心是否存在错误,或者错误的存在以某种方式表明您无法对其采取任何措施(例如,当将以前的错误写入文本日志文件时,您得到一个IOException,这意味着您无论如何都不能写出新的错误)。
只有在确实出现异常时才应该抛出异常——发生了超出正常范围的事情。一个空的catch块基本上表示“一些不好的事情正在发生,但我只是不在乎”。这是个坏主意。
如果您不想处理异常,就让它向上传播,直到它到达一些可以处理它的代码。如果没有任何东西可以处理异常,则应该关闭应用程序。
在极少数情况下,这样做是合理的。在Python中,你经常会看到这样的结构:
try:
result = foo()
except ValueError:
result = None
所以它可能是OK的(取决于你的应用程序):
result = bar()
if result == None:
try:
result = foo()
except ValueError:
pass # Python pass is equivalent to { } in curly-brace languages
# Now result == None if bar() returned None *and* foo() failed
在最近的一个. net项目中,我必须编写代码来枚举插件dll,以查找实现特定接口的类。相关的代码(在VB中。NET,对不起)是:
For Each dllFile As String In dllFiles
Try
' Try to load the DLL as a .NET Assembly
Dim dll As Assembly = Assembly.LoadFile(dllFile)
' Loop through the classes in the DLL
For Each cls As Type In dll.GetExportedTypes()
' Does this class implement the interface?
If interfaceType.IsAssignableFrom(cls) Then
' ... more code here ...
End If
Next
Catch ex As Exception
' Unable to load the Assembly or enumerate types -- just ignore
End Try
Next
尽管在这种情况下,我承认在某个地方记录失败可能是一种改进。
你不应该有一个空的catch块。这就像隐藏一个你知道的错误。至少,您应该为日志文件编写一个异常,以便稍后在时间紧迫时查看。
我认为如果你捕捉到一个特定的异常类型,你知道它只会因为一个特定的原因而被引发,并且你期待这个异常,并且真的不需要对它做任何事情,这是可以的。
但即使在这种情况下,也可能需要调试消息。