关于c#:为什么我不能写一个没有捕获或最后的尝试?

Why can't I write just a try with no catch or finally?

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

VB:

1
2
3
4
Try
    DontWannaCatchIt()
Catch
End Try

C:

1
2
3
4
5
try
{
    DontWannaCatchIt();
}
catch {}

我知道我应该抓住我期待的每一个重要的例外,并为此做些什么,但有时这并不重要——或者我做了什么错事?

try块的这种用法是否不正确,并且至少有一个catchfinally块的要求是否有指示?

更新:

现在我明白了原因,至少我应该对空catch块进行注释,这样其他人就可以理解为什么它是空的了。我也应该只抓住我期待的例外。

幸运的是,我正在用vb编码,这样我就可以用一个catch编写它:

1
2
3
4
5
6
7
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


如果你不想抓住它,为什么一开始就使用try

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

所以你估计:

1
2
3
4
5
6
7
8
9
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.
}

接住会吞下任何发生的例外。你对你的代码有信心,你能优雅地处理任何出错的事情吗?

要做的最好的事情(为了您和您的维护程序员的理智)是明确地声明您可以优雅地处理:

1
2
3
4
5
6
7
8
9
10
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.")

}


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

但是您需要让像StackOverflowExceptionOutOfMemoryException这样的异常传播。或者,更常见的是,NullReferenceException。这些异常通常是您没有预料到的错误,不能从中恢复,不能从中恢复,也不应该被抑制。

如果您想忽略一个异常,那么最好在代码中为该异常显式地编写一个空的catch块。这就清楚了你忽略了哪些例外。非常正确地忽略异常是一个选择加入过程,而不是选择退出过程。拥有一个"忽略所有异常"特性,然后可以被重写为不忽略特定类型,这将是一个非常糟糕的语言特性。

您如何知道哪些类型的异常是重要的,不应该被捕获?如果有你不知道的例外呢?你怎么知道你不会最终压制你不熟悉的重要错误?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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 (???)
{
}


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


另外,如果您没有对一个错误做些什么,也许您应该指定程序必须忽略的异常类型。

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


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

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

空catch块=忽略该块处理的错误。

注意:VBA有一个恶意的"出错时继续"…


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

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

如果您必须这样做,请尽可能具体地描述您要捕获的异常类型。如果不是,也许记录异常是一个选项。


没有catch或finally无效。空catch或finally有效。空捕获意味着你不关心异常,你只是尝试做一些事情,如果它不起作用,你就不重要了,你只是想继续下去。例如,在清理函数中很有用。


是的,不正确。就像goto:每100 kloc一个是好的,但是如果你需要很多这样的东西,你就错了。

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

1
2
3
4
5
6
7
8
9
10
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(),但这必须返回问题中的异常。


如果你只用try只写代码怎么办?

1
2
3
4
5
try
{
   int j =0;
   5/j;
}

这相当于写

1
2
 int j =0;
   5/j;

所以写尝试没有任何意义,它只会增加你的行数。

现在,如果您使用空catch或finally编写try,您将明确地指示运行时采取不同的行为。

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


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