以下捕获块之间的区别是什么?
try
{
...
}
catch
{
...
}
和
try
{
...
}
catch(Exception)
{
...
}
我意识到,在任何一种情况下,异常实例都不可用,但是有什么我可以用另一个实现的吗?
答案 0 :(得分:7)
他们几乎相同。
从C#语言规范,第8.10节:
某些编程语言可能支持不能表示为从System.Exception派生的对象的异常,尽管C#代码永远不会生成此类异常。一般的catch子句可用于捕获此类异常。因此,一般的catch子句在语义上与指定System.Exception类型的子句不同,因为前者也可以捕获来自其他语言的异常。
请注意,虽然C#在两者之间有所区别,但它们实际上与.NET 2.0相同,如this blog所述:
由于最近2.0 CLR发生了变化,如果你有代码决定在某处抛出一个int(System.Int32),那么CLR现在会用RuntimeWrappedException包装它,并且编译器已经更新为给你一个警告,上面的第二个句子现在是死代码
warning CS1058: A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a System.Runtime.CompilerServices.RuntimeWrappedException
关于CLR如何知道为程序集执行此操作,您会注意到编译器现在将RuntimeCompatibilityAttribute添加到程序集中,告诉它:
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = {property bool 'WrapNonExceptionThrows' = bool(true)}
答案 1 :(得分:7)
catch
不同,不带参数的 catch (Exception)
将捕获非符合CLS的异常。
答案 2 :(得分:4)
来自Why catch(Exception)/empty catch is bad
空catch语句可能同样糟糕,具体取决于您的语言生成的MSIL代码。 C#将一个空的catch语句转换为catch(System.Object),这意味着你最终会捕获所有异常 - 甚至是非CLS兼容的异常。 VB表现得更好,将一个空的catch语句转换为catch e作为System.Exception,它限制了你捕获符合CLS的异常。
答案 3 :(得分:3)
如果你看一下生成的IL,差异就是:
catch(Exception){}:
catch [mscorlib]System.Exception
{}
只是简单地抓住了:
catch{}:
catch [mscorlib]System.Object
{}
所以从理论上讲,如果你创建一个可以有异常的语言而不是从System.Exception继承,那就会有区别......
答案 4 :(得分:1)
非CLS附加语言(如C ++ / CLI)可以抛出不是从System.Exception类派生的对象。第一个代码示例将允许您在catch块中执行代码,但您无法检查抛出的对象本身。这几乎不是问题,但可能是。
答案 5 :(得分:0)
我不相信存在差异,像Resharper这样的工具会告诉你catch(Exception)
在第二个实例中是多余的,除非你在{之前插入了其他catch(SomeSubclassException)
异常处理块{1}}为其他异常条件应用不同的异常处理逻辑。