1、catch throw的几种形式及性能影响:
private void Form1_Click(object sender, EventArgs e)
{
try
{
}
catch
{
throw;
}
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
}
catch (Exception)
{
throw;
}
}
private void Form1_Enter(object sender, EventArgs e)
{
try
{
}
catch (Exception ee)
{
throw;
}
}
private void Form1_DoubleClick(object sender, EventArgs e)
{
try
{
}
catch (Exception ee)
{
throw ee;
}
} 对应的IL代码(以下代码是release版本的IL代码):.method private hidebysig instance void Form1_Click(object sender,
class [mscorlib]System.EventArgs e) cil managed
{
// 代码大小 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method Form1::Form1_Click
.method private hidebysig instance void Form1_Load(object sender,
class [mscorlib]System.EventArgs e) cil managed
{
// 代码大小 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method Form1::Form1_Load
.method private hidebysig instance void Form1_Enter(object sender,
class [mscorlib]System.EventArgs e) cil managed
{
// 代码大小 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method Form1::Form1_Enter
.method private hidebysig instance void Form1_DoubleClick(object sender,
class [mscorlib]System.EventArgs e) cil managed
{
// 代码大小 1 (0x1)
.maxstack 1
.locals init ([0] class [mscorlib]System.Exception ee)
IL_0000: ret
} // end of method Form1::Form1_DoubleClick 可以看到Form1_Click、Form1_Load、Form1_Enter中的try catch已经被编译器优化掉了:IL_0000: ret //即为 return 标记 返回值
只有Form1_DoubleClick中的try catch中对try catch进行了处理:
.locals init ([0] class [mscorlib]System.Exception ee) //定义 Exception 类型参数 ee (此时已经把ee存入了Call Stack中)即在Form1_DoubleClick中的try catch才会对性能产生影响。
==》可以看出一下三种try catch的写法对于release版本的代码来说是完全一样,也不会产生任何的性能消耗:
try
{
}
catch
{
throw;
}
try
{
}
catch (Exception)
{
throw;
}
try
{
}
catch (Exception ee)
{
throw;
} 对于上面的结论大家可以写测试demo验证一下 (已测试,结果与分析一致
)。 那么对于debug模式下的IL代码是什么样子的呢?
.method private hidebysig instance void Form1_Click(object sender,
class [mscorlib]System.EventArgs e) cil managed
{
// 代码大小 11 (0xb)
.maxstack 1
IL_0000: nop
.try
{
IL_0001: nop
IL_0002: nop
IL_0003: leave.s IL_0009
} // end .try
catch [mscorlib]System.Object
{
IL_0005: pop
IL_0006: nop
IL_0007: rethrow
} // end handler
IL_0009: nop
IL_000a: ret
} // end of method Form1::Form1_Click
.method private hidebysig instance void Form1_Load(object sender,
class [mscorlib]System.EventArgs e) cil managed
{
// 代码大小 11 (0xb)
.maxstack 1
IL_0000: nop
.try
{
IL_0001: nop
IL_0002: nop
IL_0003: leave.s IL_0009
} // end .try
catch [mscorlib]System.Exception
{
IL_0005: pop
IL_0006: nop
IL_0007: rethrow
} // end handler
IL_0009: nop
IL_000a: ret
} // end of method Form1::Form1_Load
.method private hidebysig instance void Form1_Enter(object sender,
class [mscorlib]System.EventArgs e) cil managed
{
// 代码大小 11 (0xb)
.maxstack 1
.locals init ([0] class [mscorlib]System.Exception ee)
IL_0000: nop
.try
{
IL_0001: nop
IL_0002: nop
IL_0003: leave.s IL_0009
} // end .try
catch [mscorlib]System.Exception
{
IL_0005: stloc.0
IL_0006: nop
IL_0007: rethrow
} // end handler
IL_0009: nop
IL_000a: ret
} // end of method Form1::Form1_Enter
.method private hidebysig instance void Form1_DoubleClick(object sender,
class [mscorlib]System.EventArgs e) cil managed
{
// 代码大小 11 (0xb)
.maxstack 1
.locals init ([0] class [mscorlib]System.Exception ee)
IL_0000: nop
.try
{
IL_0001: nop
IL_0002: nop
IL_0003: leave.s IL_0009
} // end .try
catch [mscorlib]System.Exception
{
IL_0005: stloc.0
IL_0006: nop
IL_0007: ldloc.0
IL_0008: throw
} // end handler
IL_0009: nop
IL_000a: ret
} // end of method Form1::Form1_DoubleClick 可以看出四种写法在debug模式下区别只是:rethrow与throw的区别。IL中rethrow与throw分别代表啥呢? Throw:引发当前位于计算堆栈上的异常对象。
Rethrow:再次引发当前异常。
即当我们抛出一个异常时, CLR会重新设置一个异常起始点。 CLR只记录最近一次异常抛出的位置。下面代码抛出一个异常,从而导致CLR重新设置该异常的起始点:
try
{
//一些处理
}
catch (Exception e)
{
//一些处理
throw e; //CLR认为这里是异常的起始点
} 相反,如果我们抛出一个异常对象, CLR将不会重新设置其堆栈的起始点,下面代码抛出一个异常,但不会导致CLR重新设置异常的起始点: try
{
//一些处理
}
catch (Exception e)
{
//一些处理
throw; //CLR不会重新设置异常的起始点
} C#中使用throw和throw ex抛出异常,但二者是有区别的。 在C#中推荐使用throw;来抛出异常;throw ex;会将到现在为止的所有信息清空,认为你catch到的异常已经被处理了,只不过处理过程中又抛出新的异常,从而找不到真正的错误源。
拓展阅读:
版权声明:作者:jiankunking 出处:http://blog.csdn.net/jiankunking 本文版权归作者和CSDN共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
原文地址:http://blog.csdn.net/jiankunking/article/details/49463991