string hehe = "hehe";
            string haha = "haha";
            haha = hehe;
            Console.Write    (hehe);
            Console.WriteLine(haha);
            //输出:hehehehe
            hehe = "改了";
            Console.Write    (hehe);
            Console.WriteLine(haha);
            //输出:改了hehe
            //string 类型不是一个引用类型吗?
            //既然是引用类型,那么在haha = hehe;之后haha与hehe应该是指向堆中的同一个地方
            //我感觉haha应该随着hehe的改变而改变
            //可是最后结果却不是这样
            //谁懂的过来解释一下,谢谢大家,祝大家清明节之后发大财
            Console.ReadKey();

解决方案 »

  1.   

    hehe与haha是两个独立的引用,只不过在修改之前,这两个引用指向堆中同一个位置,在
                hehe = "改了";
    之后,hehe指向另外一个位置。这里的引用,类似于C/C++中的指针,然而却不同于指针,比如在这里,如果你把引用想象为指针的话,就会妨碍你对这个问题的正确理解。
      

  2.   

    字符串比较特殊,它具体不变性,Google上搜索一下有很多
      

  3.   

    .net对字符串进行了特殊处理,每次赋值都是创建一个新的string对象,所以在有的人会误以为string是一个值类型。
      

  4.   

    由于string的immutable特性,因此每次对string的改变都会在托管堆中产生一个新的string变量,string作为参数传递时,在托管堆中会产生一个新的空间,并执行数据拷贝,所以才有了类似于按值传递的结果。
    但是根据我们的内存分析可知, string在本质上还是一个引用类型,在参数传递时发生的还是按址传递,不过由于其特殊的恒定特性,在函数内部新建了一个string对象并完成初始化,但是函数外部取不到这个变化的结果,因此对外表现的特性就类似于按值传递。
      

  5.   

    没错,string是特殊的,具有值类型的特性
      

  6.   

    4楼的就说得很清楚,string是个特殊的类型。每修改一个,都会创建一个新的string的对象。有时这样就很产生眼中的效率问题
      

  7.   

    刚开始的时候
    hehe和haha都指向同一个字符串,即"hehe";但是,hehe和haha并没有互相应用的关系。只是"碰巧"它们都指向同一个字符串。执行 hehe = "改了" 这行后hehe就指向了新的字符串,而haha还是指向旧的内容。
    .Net规定string是不可变(immutable)的,所以最开始的hehe和haha都指向同一个字符串,这样可以节省第二个拷贝,节省内存。
    你可以发现string类并不提供修改的功能。象string1.Replace(...)并不修改string1,而是将结果以新string的形式返回。
    象string1[0]可以返回第一个字符,但是你不能修改string1[0]。题外话:如果你能够直接篡改hehe指向的内容,那么haha将体现改动(记得最开始它们指向同一字符串)。
    把hehe = "改了"换成以下代码:unsafe 

      fixed (char* ptr = hehe) 
      { 
        ptr[0] = 'j'; 
      } 
    }...
    Console.WriteLine(haha);   // output  jeha
    记得编译项目选型要允许unsafe。
      

  8.   


    hehe 和haha两个名字只是引用变量而已,类似指针。它们指向string池中的实际string对象“hehe”。但当你hehe = "改了"时,只是让hehe指向了另一个string实例,并没有去修改原来的“hehe”所以结果就是这样了。