C# 为什么可以';我不是只写一次尝试,没有收获还是最后?

C# 为什么可以';我不是只写一次尝试,没有收获还是最后?,c#,.net,vb.net,exception-handling,try-catch,C#,.net,Vb.net,Exception Handling,Try Catch,有时我这样做,我也看到其他人这样做: VB: C#: 我知道我应该抓住每一个我期待的重要例外并采取一些措施,但有时这并不重要,或者我做错了什么 try块的这种用法是否不正确,至少一个catch或finally块的要求是否表明了这一点 更新: 现在我明白了原因,我至少应该评论一下空的catch块,让其他人理解为什么它是空的。我还应该只捕获我期望的异常 幸运的是,我正在用VB编写代码,因此我可以用一个catch编写它: Catch ex As Exception When TypeOf ex Is

有时我这样做,我也看到其他人这样做:

VB: C#: 我知道我应该抓住每一个我期待的重要例外并采取一些措施,但有时这并不重要,或者我做错了什么

try
块的这种用法是否不正确,至少一个
catch
finally
块的要求是否表明了这一点

更新: 现在我明白了原因,我至少应该评论一下空的catch块,让其他人理解为什么它是空的。我还应该只捕获我期望的异常

幸运的是,我正在用VB编写代码,因此我可以用一个catch编写它:

Catch ex As Exception When TypeOf ex Is IOException _
                    OrElse TypeOf ex Is ArgumentException _
                    OrElse TypeOf ex Is NotSupportedException _
                    OrElse TypeOf ex Is SecurityException _
                    OrElse TypeOf ex Is UnauthorizedAccessException
    'I don't actually care.
End Try

无捕获或最终捕获无效。空catch或finally是有效的。空捕获意味着您不关心异常,您只是尝试做一些事情,如果不起作用也没关系,您只想继续。例如,在清除函数中很有用。

此外,如果您不需要对错误采取措施,则可能需要指定程序必须忽略的异常类型


如果您必须忽略每个异常,我不明白为什么不能以这种方式使用try/catch。

我听说的原因是,如果您的尝试因任何原因失败,那么让您控制错误响应比让框架控制它(即黄屏或错误500)更可取。

这通常是一个错误。异常信号,嗯,异常行为;当抛出异常时,它应该意味着发生了错误。所以,继续正常的程序流程,就好像什么都没有出错一样,是一种隐藏错误的方式,一种拒绝的形式。相反,请考虑您的代码应该如何处理异常情况,并编写代码来实现这一点。由于您掩盖了错误而传播的错误比立即出现的错误更难调试。

这对您来说并不容易,因为大多数开发人员认为这是一种不好的做法

如果后来有人向
dontwancatchit()
的主体添加了一个方法调用,该调用确实抛出了一个值得捕获的异常,但它被您的空catch块吞没了,该怎么办?如果你真的想抓住一些例外,但当时却没有意识到,那该怎么办


如果您确实必须这样做,请尽量具体说明您将捕获的异常类型。如果没有,那么可能可以选择记录异常。

如果您只使用try编写代码会怎么样

try
{
   int j =0;
   5/j;
}
这相当于写

 int j =0;
   5/j;
所以写try没有任何意义,它只会增加你的行数

现在,如果您编写try with empty catch或finally,那么您就是在明确指示运行时采取不同的行为


所以这就是为什么我认为空的try块是不可能的。

如果您不想捕获它,为什么要首先使用
try

一个
try
语句意味着你相信某些事情可能会出错,而
catch
则表示你可以充分处理出错的事情

根据你的估计:

try
{
    //Something that can go wrong
}
catch
{
    //An empty catch means I can handle whatever goes wrong. If a meteorite hits the
    //datacenter, I can handle it.
}
捕捉会吞噬任何发生的异常。您是否对自己的代码有信心,可以优雅地处理任何出错的事情

最好的做法(为了您和您的维护程序员的理智)是明确说明您可以优雅地处理的内容:

try
{
    //Something that could throw MeteoriteHitDatacenterException
}
catch (MeteoriteHitDatacenterException ex)
{
    //Please log when you're just catching something. Especially if the catch statement has side effects. Trust me.
    ErrorLog.Log(ex, "Just logging so that I have something to check later on if this happens.")

}

是的,这是不正确的。这就像是“goto”:每100 KLoc一个就可以了,但是如果你需要很多这样的东西,你就做错了

在错误处理中,没有任何反应地接受异常是最糟糕的事情之一,它至少应该是明确的:

try  
{      
   DontWannaCatchIt(); 
}  
catch 
{
    // This exception is ignored based on Spec Ref. 7.2.a,
    // the user gets a failure report from the actual results, 
    // and diagnostic details are available in the event log (as for every exception)
} 

再远一点看:

错误处理是一个方面:在某些上下文中,需要抛出错误并将其传播到调用堆栈(例如,复制文件时,复制失败)

在不同的上下文中调用相同的代码可能需要跟踪错误,但操作必须继续(例如,复制100个文件,并用日志指示哪些文件失败)

即使在这种情况下,空的catch处理程序也是错误的

对于大多数语言,除了在循环中尝试+catch并在catch处理程序中构建日志之外,没有其他直接实现。(不过,您可以构建一个灵活的mroe机制:拥有一个每次调用线程处理程序,该处理程序可以丢弃或隐藏消息。但是,如果没有直接的语言支持,与调试工具的交互会受到影响。)



一个合理的用例是从
X()
实现
TryX()
,但这必须返回有问题的异常

存在错误,已抛出,需要转到某个位置。正常代码流已中止,需要清洁风扇

无捕捉块=不确定状态。代码应该放在哪里?它应该做什么

空的catch块=通过忽略它处理的错误


注意:VBA有一个卑鄙的“错误继续”…

不,您应该不要捕获每个重要的异常。捕获并忽略您不关心的异常是可以的,比如I/O错误,如果您无法纠正它,并且您不想麻烦向用户报告它

但您需要让异常(如
StackOverflowException
OutOfMemoryException
传播)。或者,更常见的是,
NullReferenceException
。这些异常通常是您没有预料到的错误,无法从中恢复,不应该从中恢复,也不应该被抑制

如果您想忽略一个异常,那么最好在代码中为该特定异常显式地编写一个空的catch块。这清楚地表明了您忽略了哪些异常。非常正确地忽略异常是一个选择加入过程,而不是选择退出过程。具有“忽略所有异常”功能,然后可以覆盖该功能以不忽略speci
try
{
    //Something that could throw MeteoriteHitDatacenterException
}
catch (MeteoriteHitDatacenterException ex)
{
    //Please log when you're just catching something. Especially if the catch statement has side effects. Trust me.
    ErrorLog.Log(ex, "Just logging so that I have something to check later on if this happens.")

}
try  
{      
   DontWannaCatchIt(); 
}  
catch 
{
    // This exception is ignored based on Spec Ref. 7.2.a,
    // the user gets a failure report from the actual results, 
    // and diagnostic details are available in the event log (as for every exception)
} 
try
{
}
// I don't care about exceptions.
catch
{
}
// Okay, well, except for system errors like out of memory or stack overflow.
// I need to let those propagate.
catch (SystemException exception)
{
    // Unless this is an I/O exception, which I don't care about.
    if (exception is IOException)
    {
        // Ignore.
    }
    else
    {
        throw;
    }
}
// Or lock recursion exceptions, whatever those are... Probably shouldn't hide those.
catch (LockRecursionException exception)
{
    throw;
}
// Or, uh, what else? What am I missing?
catch (???)
{
}