string str1 = "123";
            string str2 = "456";
            string str3 = "789";
            string result1 = string.Concat(str1, str2, str3);
            string result2 = string.Concat("123", "456", "789");
这里,result1 和 result2 在 MSIL 大概是这样:.locals init ([0] string str1,
           [1] string str2,
           [2] string str3,
           [3] string result1,
           [4] string result2)
  IL_0000:  nop
  IL_0001:  ldstr      "123"
  IL_0006:  stloc.0
  IL_0007:  ldstr      "456"
  IL_000c:  stloc.1
  IL_000d:  ldstr      "789"
  IL_0012:  stloc.2
  IL_0013:  ldloc.0
  IL_0014:  ldloc.1
  IL_0015:  ldloc.2
  IL_0016:  call       string [mscorlib]System.String::Concat(string,
                                                              string,
                                                              string)
  IL_001b:  stloc.3
  IL_001c:  ldstr      "123"
  IL_0021:  ldstr      "456"
  IL_0026:  ldstr      "789"
  IL_002b:  call       string [mscorlib]System.String::Concat(string,
                                                              string,
                                                              string)
  IL_0030:  stloc.s    result2
问题:这里只有声明了变量str1,str2,str3,那么在 result2 的那些“字符串常量”(姑且这么叫吧),有没有什么区别?
两者编码方式,是否有什么该注意的?

解决方案 »

  1.   

    没啥区别,你多声明了str1 到str3,要多占资源就是了,不过写死就没办法灵活赋值了,还得看实际应用的需要了
      

  2.   

    MSIL是编译后的中间语言,看编译代码是没有区别的。这几个变量在内存布局上放的不是一个地方,所以还是有区别的。
      

  3.   

    str1 到str3声明是分配了内存,不过C#中有垃圾回收机制。
    而直接赋值就不会占用内存空间,像楼上说的不够灵活。
      

  4.   

    申明变量str1,str2, str3后,会逐个分配内存。 不申明就一块分配
      

  5.   

    以前听过
    string str1 = "123";

    string str2 = "123";
    引用的是同一块内存。
    这个说法正确吗?
      

  6.   

    不完全正确...这两句的执行结果是...1.在托管堆上分配了一块内存存放"123"这个字符串值...2.在栈上为str1分配了内存存放str1的引用并将此引用指向托管堆上的字符串值"123"...3.在栈上为str2分配了内存存放str1的引用并将此引用指向托管堆上的字符串值"123"...之所以栈上两个引用都指向托管堆上同一个值,是因为.NET的字符串驻留(String Interning)技术...用来提升性能及节约内存,因为字符串是最常用的数据类型...所以实际上还有一个hashtable在存储"123"这个字符串值的hash值,它也要占用内存...当然这不需要你来管理你也管不了...这也解释了你最开始的问题...对于没有声明的字符串常量,只在托管堆上分配了内存而没有在栈上分配内存...除非它们的值和一个在使用的字符串变量值相同,否则由于引用计数为0它们实际上是垃圾对象,这些内存将很快被GC回收...3楼所谓的“直接赋值就不会占用内存空间”是毫无根据的说法...ldstr指令就是为字符串分配内存...
      

  7.   

    对, 从存储角度, string 是不可修改的, 1 修改就产生新的.
      

  8.   

    字符串字面值(literal) 有特殊对待      string str1 = "1234";
          string str2 = "1234";
          bool flag = false;
          flag = (str2 == str1);
          flag = str1.Equals(str2);
          flag = object.ReferenceEquals(str1, str2);
          
          str1 = "12" + "34";
          str2 = "1" + "234";
          flag = (str2 == str1);
          flag = str1.Equals(str2);
          flag = object.ReferenceEquals(str1, str2);      string s1 = "12";
          string s2 = "34";
          string s3 = "1";
          string s4 = "234";      str1 = s1 + s2;
          str2 = s3 + s4;
          flag = (str2 == str1);
          flag = str1.Equals(str2);
          flag = object.ReferenceEquals(str1, str2);
      

  9.   


    str1 = "12" + "34";
    str2 = "1" + "234";

    仍然跟程序中所有出现的 "1234" 字面值的量在引用上相等.
      

  10.   

    这个是被编译器优化的结果...编译时由于"12"和"34"是未被声明的字符串常量,因此直接被视为str1="1234";..."1"、"234"同理,这在IL代码中是可以看出来的...
      

  11.   

    了解了许多。谢谢 vrhero 。你的回答总能让人醍醐灌顶。