代码之家  ›  专栏  ›  技术社区  ›  LONG

两个具有相同值的不同字符串实例如何存储在堆中?

  •  -1
  • LONG  · 技术社区  · 6 年前

    以下内容:

    string A = "A";
    string A1 = "A";
    string B = "AB".Substring(0,1);
    
    Console.WriteLine("{0}", object.ReferenceEquals(A, A1));  //Returns True
    
    Console.WriteLine("{0}", object.ReferenceEquals(A, B));  //Returns Flase
    

    object.ReferenceEquals(A, A1) 返回true,因为它们是两个相同的实例,我可以理解这两个引用对堆中的同一个值(即 A ?如果我错了,怎么能用 String is immutable ?

    为了 object.ReferenceEquals(A, B) 返回false,is "AB".Substring(0,1) 单独存储在堆中 ?

    2 回复  |  直到 6 年前
        1
  •  2
  •   Dai    6 年前
    string A = "A";
    string A1 = "A";
    

    在上面的情况下,编译器设置 A A1 到可执行映像中的相同字符串文本值。

    string B = "AB".Substring(0,1);
    

    内部 Substring 分配一个新字符串,它不会执行其他语言/平台所做的“子字符串切片”优化,即使C字符串是不可变的,这是因为.NET String 类的内部值表示形式不与其他实例共享字符串数组指针。

    你可以做 B 同样的方法 String.Intern : https://msdn.microsoft.com/en-us/library/system.string.intern(v=vs.110).aspx

        2
  •  1
  •   UladzislaÅ­    6 年前

    A A1 变量在堆中存储对同一对象的引用,因为机制 String interning . 它是由编译器进行的优化,因此只适用于文本。 B 在运行时计算,因此不会将其放入池中。

    可以使用 String.Intern 方法。

    此外,还可以为特定程序集添加禁用此机制 CompilationRelaxationAttribute 具有 CompilationRelaxations.NoStringInterning 程序集级别的值。

    这种优化不是.NET特定的,例如Java具有类似的字符串池,以及从-128到127的整数以及一些其他的基元类型。