我知道下面的 catch and throw
block 是多余的,我很好奇它能造成什么样的破坏?
编译器可以在 Release模式下优化它吗?或者它无论如何都会捕获异常并重新抛出它?如果是后一种情况,会造成什么样的性能损失?
try
{
//...
}
catch {
throw;
}
最佳答案
优化
即使在发布版本中,编译器也不会对此进行优化。
采用以下测试应用程序:
public class Program {
public static void Main(string[] args) {
try {
CallsThrow();
}
catch(Exception ex) {
Console.WriteLine("Main() caught exception: " + ex.Message);
}
Console.Read();
}
private static void CallsThrow() {
try {
Throw();
}
catch {
throw;
}
}
private static void Throw() {
throw new Exception("Here's my exception.");
}
}
使用 ILSpy我们可以在 IL 查看输出二进制文件等级。我们看到 CallsThrow
中的 try
/catch
仍然存在于我们的 Release 二进制文件中:
.method private hidebysig static
void CallsThrow () cil managed
{
// Method begins at RVA 0x2094
// Code size 11 (0xb)
.maxstack 1
.try
{
IL_0000: call void JunkCSharpConsole.Program::Throw()
IL_0005: leave.s IL_000a
} // end .try
catch [mscorlib]System.Object
{
IL_0007: pop
IL_0008: rethrow
} // end handler
IL_000a: ret
} // end of method Program::CallsThrow
基准
代码:
public class Program
{
public static void Main(string[] args) {
const int N = 100000000;
#if DEBUG
const string mode = "Debug";
#else
const string mode = "Release";
#endif
Console.WriteLine("Testing {0} iterations in {1} mode:", N, mode);
// Attempt to JIT / cache
CallsThrowWithTryCatch(false);
CallsThrowWithoutTryCatch(false);
// Test with try/catch+throw
var s1 = Stopwatch.StartNew();
for (int i = 0; i < N; i++ )
CallsThrowWithTryCatch(false);
s1.Stop();
Console.WriteLine(" With try/catch: {0} ms", s1.ElapsedMilliseconds);
// Test without try/catch+throw
var s2 = Stopwatch.StartNew();
for (int i = 0; i < N; i++)
CallsThrowWithoutTryCatch(false);
s2.Stop();
Console.WriteLine(" Without try/catch: {0} ms", s2.ElapsedMilliseconds);
var pct = (s1.ElapsedMilliseconds - s2.ElapsedMilliseconds) / (double)s1.ElapsedMilliseconds * 100.0;
Console.WriteLine("No try/catch faster by {0:.02}%", pct);
// Just show that it works
try {
CallsThrowWithTryCatch(true);
}
catch (Exception ex) {
Console.WriteLine("Main() caught exception: " + ex.Message);
}
// Wait to exit
Console.WriteLine("Press ENTER to exit.");
Console.Read();
}
private static void CallsThrowWithTryCatch(bool doThrow) {
try {
Throw(doThrow);
}
catch {
throw;
}
}
private static void CallsThrowWithoutTryCatch(bool doThrow) {
Throw(doThrow);
}
private static void Throw(bool doThrow) {
if (doThrow)
throw new Exception("Here's my exception.");
}
}
结果:
Testing 100000000 iterations in Debug mode:
With try/catch: 1492 ms
Without try/catch: 1474 ms
No try/catch faster by 1.22%
Main() caught exception: Here's my exception.
Press ENTER to exit.
Testing 100000000 iterations in Release mode:
With try/catch: 598 ms
Without try/catch: 458 ms
No try/catch faster by 23.42%
Main() caught exception: Here's my exception.
Press ENTER to exit.
我们可以看到,是的,即使是空的 try
/catch
, 也会带来性能损失。在 Debug 版本中,它不是那么重要,但是通过删除 try
/catch
,Release 版本显示出 23.42% 的实质性改进。
关于.net - 空的 catch 和 throw block 会做什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19920063/