【问题标题】:Reference object comparison of type string字符串类型的引用对象比较
【发布时间】:2013-09-02 14:58:41
【问题描述】:

考虑以下代码:

public static void Main()
{
    string str1 = "abc";
    string str2 = "abc";

    if (str1 == str2)
    {
        Console.WriteLine("True");
    }
    else
    {
        Console.WriteLine("False");
    }

    Console.ReadLine();
}

输出为“真”。 string 是 .Net 中的引用类型,我正在比较两个不同的对象,但输出仍然是“True”。

  1. 是因为它在比较两个对象之前在内部调用了ToString() 方法吗?
  2. 还是因为string 是不可变类型?两个完全不同具有相同值string对象会指向堆上相同的内存位置吗?

string 比较是如何发生的?

内存分配是如何在堆上工作的?具有相同值的两个不同的string 对象会指向相同的内存位置,还是指向不同的位置?

【问题讨论】:

  • 起初我觉得“没有足够的研究”投反对票,因为您很快就会发现 string 是 .net 中引用类型的一个特例,但是看到了一些答案和 cmets你的问题已经产生了我实际上学到了一些东西,所以+1!

标签: c# .net string operators


【解决方案1】:
  • 默认情况下按值比较字符串。
  • 默认情况下通过引用比较对象。
  • 同一程序集中的相同字符串 literalsinterned 是相同的引用。
  • 字面量的相同字符串可以合法地被嵌入到相同的引用中,但实际上通常不是。

所以现在你应该能够理解为什么你会在这个程序片段中得到给定的输出:

string a1 = "a";
string a2 = "a";
string aa1 = a1 + a2;
string aa2 = a1 + a2;
object o1 = a1;
object o2 = a2;
object o3 = aa1;
object o4 = aa2;
Console.WriteLine(a1 == a2);   // True
Console.WriteLine(aa1 == aa2); // True
Console.WriteLine(o1 == o2);   // True
Console.WriteLine(o3 == o4);   // False

这有意义吗?

【讨论】:

    【解决方案2】:

    对于字符串类型,== 比较字符串的值。

    http://msdn.microsoft.com/en-us/library/53k8ybth.aspx

    关于您关于寻址的问题,几行代码表明它们将具有相同的地址。

    static void Main(string[] args)
    {
        String s1 = "hello";
        String s2 = "hello";
        String s3 = s2.Clone() as String;
    
        Console.Out.WriteLine(Get(s1));
        Console.Out.WriteLine(Get(s2));
        Console.Out.WriteLine(Get(s3));
    
        s1 = Console.In.ReadLine();
        s1 = Console.In.ReadLine();
        s3 = s2.Clone() as String;
    
        Console.Out.WriteLine(Get(s1));
        Console.Out.WriteLine(Get(s2));
        Console.Out.WriteLine(Get(s3));
    }
    
    public static string Get(object a)
    {
        GCHandle handle = GCHandle.Alloc(a, GCHandleType.Pinned);
        IntPtr pointer = GCHandle.ToIntPtr(handle);
        handle.Free();
        return "0x" + pointer.ToString("X");
    }
    

    每组测试的结果相同。

    Get() 感谢Memory address of an object in C#

    【讨论】:

    • 堆中的内存分配是如何发生的?两个不同但具有相同值的字符串对象是否会指向相同的内存位置???
    • 是的,他们将拥有相同的地址。查看更新的答案。
    • @AtulSureka 实际上 2 个不同的字符串可以有不同的地址,但是 compiler 对其进行了优化,因此所有相同的字符串都将分配到相同的地址,因为字符串是只读或不可变。
    【解决方案3】:

    String 类已完成运算符重载,以便为 == 运算符编写自定义逻辑。

    这就是为什么当 == 用于字符串时,它不比较引用而是实际值。

    【讨论】:

      【解决方案4】:

      更多信息请查看https://stackoverflow.com/a/1659107/562036

      很可能很大一部分开发人员来自 来自 Java 背景,其中使用 == 比较字符串是错误的,并且 不起作用。在 C# 中没有(实际的)区别(对于字符串)。

      【讨论】:

        【解决方案5】:

        string 是引用类型,因为它没有默认分配大小,但出于理智的原因被视为值类型,你能想象一个世界吗?== 不能在精确的字符串值之间工作。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多