关于String类型

     老早之前,有一个很有意思的帖子(string 引用类型,还是值类型),引来了热烈的讨论。当时把它给收藏了。这几天,闲来无事,翻看收藏夹的时候,又看到了它,觉得很有意思,研究了研究。有了一点点拙见。
      首先,String是引用类型,这肯定是勿庸置疑的。String是继承自System.Object类型的,而不是象Int32一样,继承自System.ValueType。但是String也是一个比较奇特的类型,一般而言,一个引用类型,构造的时候,是调用的IL指令:newobj。但是String有它自己的特殊的IL指令:ldstr。这说明,虽然String也是引用类型,但是,它和其他的引用类型还是有一些区别的。具体而言,CLR使用了字符串驻留技术,来提升String的性能。
      简单的说,字符串驻留技术保证:内容相同的字符串,其在托管堆栈上的地址也是相同的,这样,就避免了大量的相同的String实例的存在 ,从而提高程序的性能,下面的代码可以验证这一点。       
       string s = "1112";
       MessageBox.Show(object.ReferenceEquals(s,"1112").ToString())
;
       上面的结果,是True。
      此外,字符串,还有一个特性,是恒定性。qqchen对这个也做了讨论。
      我们可以看看下面的代码。
          unsafe{

         string s = "123";
         string b = "123";

         fixed(char* p = s)
        {
               System.IntPtr ip = (System.IntPtr)p;
               Console.WriteLine("这是s的初始地址,{0}",ip.ToString());
        }

        fixed(char* p = b)
       {
               System.IntPtr ip = (System.IntPtr)p;
               Console.WriteLine("这是b的地址,{0}",ip.ToString());
       }


       s = "234";

      fixed(char* p = s)
     {
            System.IntPtr ip = (System.IntPtr)p;
            Console.WriteLine("这是s的修改后地址,{0}",ip.ToString());
     }

     fixed(char* p = b)
     {
           System.IntPtr ip = (System.IntPtr)p;
          Console.WriteLine("这是b在s修改后的地址,{0}",ip.ToString());
      }

    }

     从上面的代码中,我们不难看出,s和b,一开始的时候,其地址是一样的,修改了s之后,s的地址就改变了,而b还是不变的。这就是string的恒定性和字符串驻留的具体体现。

     我主要想说的,是String作为参数传递的问题。同所有的引用类型一致,String作为参数传递的时候,传递了地址的拷贝,就象值类型传递的是值拷贝一样。
     有时候,可能会有这样的迷惑,既然String是按照地址来传递的,那么我在方法内部修改了String,为什么外部的String没有受到影响?比如下面的代码:
     string s = “初始值”;
     public void ChangeStr(string varStr)
    {
          varStr = “修改了!“;
    }

    在调用ChangeStr(s)之后,s的内容仍然是“初始值”,这是为什么呢?

    其原因就是:虽然varStr和s的地址,开始的时候是一致的,但是在修改了varStr的内容之后,他们的地址就不一致了!这个在上面的代码中其实可以体现出来。
我们还是用代码进行验证:
    unsafe
   {
    string s = "123";

    fixed(char* p = s)
    {
     System.IntPtr ip = (System.IntPtr)p;
     Console.WriteLine("这是s的初始地址,{0}",ip.ToString());
    }

    ChangedStr(s);
   }
   public void ChangedStr(string s)
  {
   unsafe
   {
    fixed(char* p = s)
    {
     System.IntPtr ip = (System.IntPtr)p;
     Console.WriteLine("这是参数s的初始地址,{0}",ip.ToString());
    }

    s = "134";

    fixed(char* p = s)
    {
     System.IntPtr ip = (System.IntPtr)p;
     Console.WriteLine("这是参数s修改后的地址,{0}",ip.ToString());
    }

   }

     上面代码的运行结果,是,参数s修改后的地址,已经和传递进来的地址不一样了。
     这样,我们就明白了,【在调用ChangeStr(s)之后,s的内容仍然是“初始值”,这是为什么呢?】这个问题。
     如果我们要得到这个修改后的结果,那么,只能用ref来修改传递的规则。public void ChangedStr(ref string s),这样,才能得到修改后的值。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值