C# 中 == 运算符和 Equals() 方法之间的区别
本文关键字:方法 之间 区别 Equals 运算符 | 更新日期: 2023-09-27 18:26:37
==
和Equals()
有什么区别?我知道==
用于比较运算符,Equals()
方法用于比较字符串的内容。所以我试过
// first example
string s1 = "a";
string s2 = "a";
Console.Write(a.Equals(s2)); // returns true, but if I assign "b" to s2,
// then result will be false
// second example
string s1 ="a";
string s2 ="a";
Console.Write(s1 == s2); // returns true
怎么会这样?两者都是不同的对象引用。假设我们认为这些是参考。但我试着这样使用
string s1 = new string("ab");
string s2 = new string("ab");
我收到无法将字符串转换为字符的编译时错误
有几件事正在发生。首先,在这个例子中:
string s1 = "a";
string s2 = "a";
Console.WriteLine(s1 == s2);
您声称:
两者都是不同的对象引用。
由于字符串实习,情况并非如此。 s1
和 s2
是对同一对象的引用。C# 规范保证 - 从 C# 4 规范的第 2.4.4.5 节:
当根据字符串相等运算符 (§7.10.7( 等效的两个或多个字符串文本出现在同一个程序中时,这些字符串文本引用同一个字符串实例。
所以在这种特殊情况下,即使你打印了object.ReferenceEquals(s1, s2)
,或者如果你使用它使用与==
的真实引用恒等式比较,你仍然会得到"true":
object s1 = "a";
object s2 = "a";
Console.WriteLine(s1 == s2); // Still prints True due to string literal interning
但是,即使这些是对单独对象的引用,==
也会重载 string
。重载是编译时决策 - 要使用的实现取决于操作数的编译时类型。所以例如:
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a == b); // Uses string's implementation, prints True
object c = a;
object d = b;
Console.WriteLine(c == d); // Reference identity comparison, prints False
将其与虚拟方法object.Equals(object)
进行比较。碰巧的是,String
也会重载此方法,但重要的是它会覆盖它。因此,如果我们将代码更改为:
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a.Equals((object) b));
object c = a;
object d = b;
Console.WriteLine(c.Equals(d));
。那么编译代码中的两个方法调用将只是 to object.Equals(object)
,但由于多态性,它们仍将都打印 True:将使用 String
中的实现。
下面是对重载方法的调用
:string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a.Equals(b)); // Calls string.Equals(string)
引用自 Equals 的文档:
Equals 的默认实现支持引用相等 引用类型,以及值类型的按位相等。参考 相等意味着比较的对象引用引用 相同的对象。按位相等意味着比较的对象具有 相同的二进制表示形式。
和 == 运算符:
对于预定义的值类型,相等运算符 (==( 返回 true 如果 其操作数的值相等,否则为 false。供参考 字符串以外的类型,如果其两个操作数引用 true,则 == 返回 同一对象。对于字符串类型,== 比较 字符串。
现在回到你的问题:为什么s1 == s2
返回 true?字符串是 .NET 中的特殊野兽。它们表示不可变的引用类型。他们被拘留在 .NET 中。这意味着,如果您有 2 个具有相同值的字符串常量,它们将在运行时引用相同的对象实例。
引用文档:
公共语言运行库通过维护 表,称为实习生池,包含对 以编程方式声明或创建的每个唯一文本字符串 您的程序。因此,具有 特定值在系统中仅存在一次。
你在想似乎是Java式的。在 java 中,==
运算符无法自定义,因此对于引用类型,它始终表示引用相等,而对于基元类型则表示值相等。另一方面,Equals
用于检查引用类型中的值相等性。
不过,在 C# 中情况有所不同。Equals
和==
都可以具有自定义实现。区别在于Equals
是虚拟(实例(方法,而operator==
是静态方法。除此之外,它们可以以完全相同的方式行事。
默认情况下,Equals
和 ==
都会检查引用类型的引用相等性,以及值类型的值相等性。但是,对于string
,两者都是自定义的,以检查值相等性。