代码改变世界

很简单的异常处理,不过一些细节你注意了吗(一):终止处理

2012-01-05 14:08  PeterWang2004  阅读(561)  评论(4编辑  收藏  举报

  try{...}finally{...}代码块已经在我们的日常开发工作中大量的使用,甚至在.net 2.0中出现了using语句来简化try{...}finally{...}操作。这种编程方式在windows编程中我们把它叫做“终止处理”。当try语句中发生异常时,线程不会立刻停止,而是会执行finally中的代码后再停止(没有异常恢复的情况,即没有Catch,本篇讨论的都是try{...}finally{...}),正因为如此,我们常常在finally中,做一些简单的操作,比如释放资源。但有下面几个问题,不知朋友们在开发过程中,注意过没有。

0.测试语句

  如果没有特别说明测试代码,均以下面这段代码作为测试语句:

 static void Main(string[] args)
{
Console.WriteLine(GetValue());
Console.ReadKey();
}

 

1.在try中带return语句

static int GetValue()
{
int temp = 0;
try
{
temp++;
return temp;
}
finally
{
temp++;
}

}

  这段代码执行后,返回的值是多少呢?是1,还是2?


2.在try中带continue、break语句

 static int GetValue()
{
int temp = 0;
while (temp < 10)
{
try
{
temp++;
if (temp == 2)
continue;
if (temp == 3)
break;
}
finally
{
temp++;
}
}
return temp;
}


   这段代码中循环执行了多少次呢?返回的值是多少呢?

3.在try中带goto语句

static int GetValue()
{
int temp = 0;
try
{
goto A_0;
}
finally
{
temp++;
}
A_0:
return temp;
}

   返回多少呢?1还是0?

4.在try中带yield return语句

static void Main(string[] args)
{
foreach (var item in GetValue())
{
Console.Write("{0} ", item);
}
Console.ReadKey();
}

static IEnumerable<int> GetValue()
{
int[] s = { 1, 2, 3, 4, 5 };
for (int i = 0; i < s.Length; i++)
{
try
{
yield return s[i];
}
finally
{
s[i]++;
}
}

}

  循环结束后,返回多少呢?是“1,2,3,4,5”还是“2,3,4,5,6”?

  如果,你可以对上面的问题,应答如流,并说出其中的处理方式,那么恭喜你,你已经掌握了终止处理,谢谢你的光临!反之,请阅读后面的篇幅。

总结

1:正确答案是1,这个问题之所以是1,是因为如果在try中使用了return语句,那么编译器会对这个return语句做一些特别的处理。它会把return语句的结果放到一个临时变量中,然后执行finally中的代码。当finally执行完毕后再返回这个临时变量。如果你对 Windows编程熟悉的话,应该知道这种技术叫做“局部展开”。

2:正确答案是循环执行2次,返回值是4,这种情况属于跳转退出try语句块,同样会执行finally,由于这样跳转会花费大量的时间,所以编译器为我们进行了一些处理,将内部的一些跳转逻辑判断放到最近的finally语句块之后,使用_leave(windows里面,_leave表示跳转到try语句最后)来退出try。

3:正确答案是1,详情在第二点中已经解释。

4:正确答案是“1,2,3,4,5”,这一点需要大家对yield return的处理有一定的了解,具体迭代器的处理请查看相关资源,我在这里要说明的是,在处理之后,yield return仍然具有和第一点相同的处理方式。