最近发现很多人在这里存在误区,特发贴纠正一下,有不同意见的地方尽量提出大家一起讨论,如下语句:(catch语句也和try一样)
------------------------------------------------------------------------
private StringBuilder Test()
{
 StringBuilder strb = new StringBuilder("A");
 try
 {
  //这里计算出的结果是"AB",但最终的返回结果是"ABC"
  return strb.Append("B");
 }
 finally
 {
  //这里的strb.ToString()应该是"AB"
  MessageBox.Show("finally:"+strb.ToString());
  strb.Append("C");
 }
}
------------------------------------------------------------------------
顺序:
在try中的return语句执行,然后执行finally块,最后返回结果。详细:
return语句执行,即执行了strb的Append("B")方法,所以finally块中strb的值为"AB"。
但并不是马上返回结果,而是再转向finally块,因此strb.Append("C")得以执行。strb的值变成"ABC"。
执行完finally后再转到try中的return返回对象strb的最终值"ABC",而不是"AB"。更不是"ACB"。[C#]中finally块不可以有return语句。
[Java]中若finally块出现return则覆盖try,catch语句的return。

解决方案 »

  1.   

    private StringBuilder Test()
    {
     StringBuilder strb = new StringBuilder("A");
      try
       {
       } 
      catch
       {
       }
      finally
      {
     
       }
      return result;
    }
    我一般是这样做...
      

  2.   

    楼上的兄弟们的说法有一点错误,return strb.Append("B");返回的strb,它是StringBuilder类的一个实例,返回就应该是对象的引用,而不是对象,在外面的语句中比如StringBuilder sb = Test(),这时sb和strb只是引用了同一个对象而已。而在finally中,strb.Append("C");这句是给对象追加了"C",所以sb指向的对象必然是ABC。(sb是指向一个对象的引用)如果改一下代码:
    string Test()
    {
    StringBuilder strb = new StringBuilder("A");
     try
     {
      //这里计算出的结果是"AB",但最终的返回结果是"ABC"
      strb.Append("B");
      return strb.ToString();
     }
     finally
     {
      //这里的strb.ToString()应该是"AB"
      MessageBox.Show("finally:"+strb.ToString());
      strb.Append("C");
     }
    }
    这样的话,string str=Test(),你看看接收到的就是AB了,而不是ABC。因为strb.ToString();返回的已经是一个转换后的新的string对象的引用,在return strb.ToString();时其实先创建一个string对象,再将这个对象的引用返回。
    --以上调试通过--
    这样说不知道大家明白了不?
      

  3.   

    --补充一下--
    return strb.Append("B");其实已经就是最终返回的值,不过这里返回的是一个引用,你之所以得到ABC是因为你又在finally中改变了引用的真实对象的值!
      

  4.   

    同意楼上
    private int test()
    {
    int i = 0;
    try
    {
    i += 1;
    return i;
    }
    catch
    {
    return i;
    }
    finally
    {
    i += 1;
    }
    }
    返回的是1而不是2.
      

  5.   

    lovinger2000(EUDEV.NET) 才是正确的答案。
    而且这纯粹是一些基础概念的问题,微软在表述上没有任何问题,并且大多数人也能理解正确。finally块中的代码将在离开try块或catch块时执行。而任何一个return语句的执行顺序是:
    先计算表达式的结果,然后将结果返回作为调用表达式的值。
    只有将结果返回作为调用表达式的值这个步骤才会导致代码离开try块。所以finally执行的时机便在此时。而return后面的表达式的结果是一个临时变量,是一个没有名字的临时变量。你无法通过任何代码来更改这个临时变量的值,因为它没有名字来标识。但,当这个临时变量是引用的时候,你可以利用引用的特性令这个临时变量引用的对象发生改变,但这并没有改变这个临时变量!。实际上在上面的例子中,无论你在finally中写什么代码都不能使得return的返回结果是一个null值,因为你无法改变这个临时变量。
    实际上引用和实例的概念到是经常有人搞不清。。
      

  6.   

    楼主说的没错,lovinger2000(EUDEV.NET)也说的没错, Ivony() 也对。
    只是你们表达的不同的东西而已,楼主的意思只是提醒大家即使“return了”,“finally块”中的语句还是照样执行,返回一个变化了的ABC只为了更好的指明“finally”被执行了而已。另外2位确是想尽办法让“finally的执行不要影响return的结果”,表达的是不同的方面的事情。你们2位没看明白楼主的意思。大家说的都对。
      

  7.   

    同意 syeerzy(快乐永远)  的说法. 希望这种讨论要经常开展.
      

  8.   

    lovinger2000(EUDEV.NET) 说得很清楚..用返回实例来说明问题..
    而楼主的操作因引用来说明问题..我对引用和实例的概念也更好理解了..谢谢
      

  9.   

    就是 return strb.ToString();   //返回一个当前值
    与   return strb               //返回一个引用
    的不同。楼主强调了“finally”任何情况都会执行,细致,细致。
      

  10.   

    private StringBuilder Test()
    {
     StringBuilder strb = new StringBuilder("A");
      try
       {
       } 
      catch
       {
       }
      finally
      {
     
       }
      return result;
    }
      

  11.   

    对头!
    finally里面的东东,不管什么情况下都会执行的。
    以前我就没理解呀。
      

  12.   

    哈哈,首先感谢大家跟我一起讨论!我最开始给别人举例其实是用的lovinger2000(EUDEV.NET)举的例子,但别人用我现在这个例子反驳我,其实都是一样的道理,我把上面的关键句子改个写法:
    return (strb.Append("B"));   //结果返回strb的引用,是可变的
    那么括号中的值很明显就是strb的引用。如果是:
    return (strb.Append("B").ToString());   //结果返回"AB"的引用
    括号中的值就应该是函数执行之后的String的引用(仍然是引用不是值,因为String类型也是引用类型,只是String类型是固定空间的不可更改的类型,它的每一次表面上的更改是返回一个新的String对象)。我举这个例子目的是强调其执行顺序,而忽略了引用与值类型。我承认前面的说法有误导,呵呵!我的目的主要是指向前段时间的网上比较流行的<Java36道经典面试题>所公布的标准答案,答案中说:
    try块执行到return语句时会先转向finally,执行完finally后再执行return语句,这很容易让人产生误解,以为strb.Append会等finally执行完才执行----所以我才取名为[澄清]。欢迎有问题的继续讨论……                                            ----楼主
      

  13.   

    返回数据的规则:
    值类型则返回其拷贝。
    引用类型返回引用。
    (其实你仍然可以认为是返回的值的拷贝,只是这个值是一个引用,类似于C++中的指针变量)
    String也是一样,只是String是不可变的引用类型,在很多情况下他更像值的行为。                                              ----楼主
      

  14.   

    谢谢大家,真是上了一课,学习ing
      

  15.   

    中方承诺修复日本使馆 赔偿问题取得进展 
    http://www.phoenixtv.com/phoenixtv/72622743014604800/20050511/547996.shtml
      

  16.   

    十分感谢 楼主指点..
    谢谢~
    Thank you very much~
    再帮你顶
      

  17.   

    还是有一个对执行顺序的理解的问题在try块中执行return expression;对执行顺序的错误的理解:
    在计算完expression后,将要返回的一刹那,先执行finally子句,然后再实际返回。对执行顺序的正确的理解:
    在计算完expression后,在返回的一刹那,先实际返回,然后再执行finally子句,然后再最终返回。
      

  18.   

    楼上:
      是吗?我只是推测。  那么请问Java中的finally中的return覆盖try中的return怎么解释?
    另:
    [共享3]C#的字符编码的理解,迷惑了我很久:
    http://community.csdn.net/Expert/topic/4002/4002354.xml
    [共享2]值传递和引用传递的讨论:
    http://community.csdn.net/Expert/topic/3999/3999829.xml                                         ----楼主
      

  19.   

    经测试,try中的return的值是不能被finally更改的。
    前面的更改只是因为是引用。
    测试代码:class form1
    {
      static void main()
      {
        MyInt my = TestBool(); //my.i最终值为2
      }
      MyInt TestBool()
      {
        MyInt d = new MyInt(1);
        try
        {
        return d.Do();
        }
        finally
        {
          d.Do();
        }
      }
    }public struct MyInt
    {
      public MyInt(int b)
      {this.i = b;}
      public MyInt Do()
      {
        this.i++;
        return this;
      }
      public int i;
    }
      

  20.   


    Java里没有指针的概念,但是如果程序员脑袋里没有指针的概念就成不了合格的Java程序员。
      

  21.   

    各位高手,我是一名新手我本来是想请教问题的,但弄了半天老是发不上去;具体问题如下:我买了一张Jbuilder9的安装盘,在我宿舍的机上上安装好了也可以用!但拿到实验室去安装以后也生成了序列号并保存了,然后再点开却出现“GUI laucher must be named <name>W.exe”字样;期间我尝试过改变安装路径,重启机子等等方法还是不行,点开Jbuilder9以后老是弹出GUI laucher must be named <name>W.exe对话框。所以很郁闷!如果有高手知道是什么原因,请告诉我,本人万分感谢!
      

  22.   

    楼主正确,不过楼主举的例子不能运行,为了说名问题更改如下:
    public class test {
        public test(){
        }
       static Object pri(){
            StringBuffer b= new StringBuffer("a");
            try{  
               return b.append("B");//这一句和 b.append("B");return b;
                                     效果是一样的,这样写更容易理解
           }finally{
               b.append("c");
               return null;
           }    }
        public static void main(String[] args)throws Exception {
            System.out.println(pri());打印为null
       }
    }
      

  23.   

    个人认为,这种写法应该像goto一样,一般不要用。
      

  24.   

    支持:  
            Ivony() ( ) 信誉:100  
            
      

  25.   

    但在finally里写return是不好的做法,从c#的态度就能看出来