20

==和with 有什么区别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");

我收到无法将字符串转换为字符的编译时错误

4

3 回答 3

26

有几件事正在发生。首先,在这个例子中:

string s1 = "a";
string s2 = "a";
Console.WriteLine(s1 == s2);

您声称:

两者都是不同的对象引用。

由于string interning ,这不是真的。s1并且s2是对同一个对象的引用。C# 规范保证 - 从 C# 4 规范的第 2.4.4.5 节:

当根据字符串相等运算符(第 7.10.7 节)等效的两个或多个字符串文字出现在同一程序中时,这些字符串文字引用相同的字符串实例。

所以在这种特殊情况下,即使你打印了,你仍然会得到“真实” object.ReferenceEquals(s1, s2),或者如果你让它使用真实的参考身份比较==

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),但由于多态性,它们仍将String打印 True :将使用 in 的实现。

下面是对重载方法的调用:

string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a.Equals(b)); // Calls string.Equals(string)
于 2012-03-02T07:20:46.827 回答
7

引用Equals的文档:

Equals 的默认实现支持引用类型的引用相等,以及值类型的按位相等。引用相等意味着被比较的对象引用指向同一个对象。按位相等意味着被比较的对象具有相同的二进制表示。

== 运算符:

对于预定义的值类型,相等运算符 (==) 如果其操作数的值相等则返回 true,否则返回 false。对于字符串以外的引用类型,== 如果它的两个操作数引用同一个对象,则返回 true。对于字符串类型,== 比较字符串的值。

现在回到你的问题:为什么s1 == s2返回 true?字符串是 .NET 中的特殊野兽。它们代表不可变的引用类型。他们在 .NET 中实习。这意味着如果您有 2 个具有相同值的字符串常量,它们将在运行时引用相同的对象实例。

文档中引用:

公共语言运行时通过维护一个称为实习池的表来保存字符串存储,该表包含对程序中以编程方式声明或创建的每个唯一文字字符串的单个引用。因此,具有特定值的文字字符串的实例在系统中仅存在一次。

于 2012-03-02T07:19:05.640 回答
2

你的想法似乎是 Java 风格的。在java中,==操作符不能自定义,所以对于引用类型,它总是意味着引用相等,而对于原始类型,它意味着值相等。另一方面,Equals用于检查引用类型中的值相等性。

但是,C# 中的情况有所不同。两者都Equals可以==有自定义实现。区别在Equals于是虚拟(实例)方法,operator==而是静态方法。除此之外,它们的行为方式完全相同。

默认情况下,两者都Equals检查==引用类型的引用相等性和值类型的值相等性。但是,对于string,两者都被定制为检查值是否相等。

于 2012-03-02T07:25:34.063 回答