许明会的计算机技术主页

Language:C,C++,.NET Framework(C#)
Thinking:Design Pattern,Algorithm,WPF,Windows Internals
Database:SQLServer,Oracle,MySQL,PostSQL
IT:MCITP,Exchange,Lync,Virtualization,CCNP

导航

学员面试题:考察Try-Catch语句的执行流程及返回细节.

C#中Try-Catch语句大家都很熟悉了,但是细究起来,还是有很多东西可讲的.
如try不能单独出现,必须和catch或者finally中的一个语句块匹配,在catch块里面执行return等细节需要反汇编才能清楚.
下面是我测试的结果. 你试试看,答对的概率是多少??
/*--===------------------------------------------===---
作者:许明会
日期:2008年1月25日 11:15:03
目的:测试Try Catch 在函数内的返回值.
1).有try就必须有catch和finally里面的一个,try不可单独存在
2).finally里面不能有控制转移语句离开finally体
3).结果:60
 * 将24和46行的throw语句注释后输出:34 134 70

--===------------------------------------------===---
*/

using System;

namespace xumh
{
    
public class runMyApp
    
{
        
static void GetValue(int i)
        
{
            
string s = "";

            
try
            
{
                
if (i == 1)
                    s 
+= "1";
                
throw new Exception();    //try块总会抛出异常,考虑注释掉会怎样
            }

            
catch
            
{
                s 
+= "2";
                
return;//遇到return,先执行finally完成后再处理return
            }

            
finally
            
{
                s 
+= "3";//finally语句体内部不能出现return跳出语句
            }

            
//因为try块总会抛出异常,而catch块又有return,下面的语句就永远不会执行
            s += "4";
            Console.WriteLine(s);
        }


        
static int GetValue()
        
{
            
int i = 10;
            
try
            
{
                i 
+= 20;
                
throw new Exception();
            }

            
catch
            
{
                i 
+= 30;
                
return i;
//注意反汇编的细节:先把30存入了eax寄存器进而写入堆栈(返回地址)
//finally语句体只是操作变量i,不再向返回地址处写入变量值,返回值是
/*
return i;
00000061  mov         eax,dword ptr [ebp-3Ch] 
00000064  mov         dword ptr [ebp-40h],eax 
00000067  call        79267E8D 
0000006c  mov         dword ptr [ebp-20h],0 
00000073  mov         dword ptr [ebp-1Ch],0FCh 
0000007a  push        0CA13C1h 
0000007f  jmp         00000081 
}                 * 
*/

            }

            
finally
            
{
                i 
+= 40;
            }

            
return i;
        }


        
static void Main()
        
{
            GetValue(
0);
            GetValue(
1);
            
int num = GetValue();
            Console.WriteLine(num);
        }

    }

}
我们修改上述代码使其在Java环境测试,结果一样,但是JavaC将无法访问的代码视为错误,而C#只是警告.
/*--===------------------------------------------===---
作者:许明会
日期:2008年1月25日 11:15:03
目的:测试Try Catch 在函数内的返回值.
1).有try就必须有catch和finally里面的一个,try不可单独存在
2).finally里面不能有控制转移语句离开finally体
3).结果:不能编译通过,若去掉32,34,57行无法访问的语句,则60
 * 若将20和42行的throw语句注释后输出同C#:34 134 70
--===------------------------------------------===---
*/

public class InterView
{
    
static void GetValue(int i)
    
{
        String s 
= "";

        
try
        
{
            
if (i == 1)
                s 
+= "1";
            
throw new Exception();    //try块总会抛出异常,考虑注释掉会怎样
        }

        
catch(Exception ex)
        
{
            s 
+= "2";
            
return;//遇到return,先执行finally完成后再处理return
        }

        
finally
        
{
            s 
+= "3";//finally语句体内部不能出现return跳出语句
        }

        
//因为try块总会抛出异常,而catch块又有return,下面的语句就永远不会执行
        s += "4";
        System.out.println (s);
    }


    
static int GetValue()
    
{
        
int i = 10;
        
try
        
{
            i 
+= 20;
            
throw new Exception();
        }

        
catch(Exception ex)
        
{
            i 
+= 30;
            
return i;
//注意反汇编的细节:先把30存入了eax寄存器进而写入堆栈(返回地址)
//finally语句体只是操作变量i,不再向返回地址处写入变量值,返回值是
        }

        
finally
        
{
            i 
+= 40;
        }

        
//java和c#一样检测到该语句没有机会执行
        
//C#将警告,而Javac不让程序编译通过.
        return i;
    }


    
public static void main(String[] args)
    
{
        GetValue(
0);
        GetValue(
1);
        
int num = GetValue();
        System.out.println (num);
    }

}


posted on 2008-01-25 13:01  许明会  阅读(932)  评论(1编辑  收藏  举报