C#中==运算符和Equals()方法的区别?

时间:2012-03-02 07:15:02

标签: c# string equals equals-operator

==Equals()之间的区别是什么?我知道==用于比较运算符,Equals()方法用于比较string的内容。所以我试过

// 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");

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

3 个答案:

答案 0 :(得分:22)

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

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

你声称:

  

两者都是不同的对象参考。

由于字符串实习,这不是真的。 s1s2是对同一对象的引用。 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));

...然后编译代码中的两个方法调用都只是object.Equals(object),但由于多态性,它们仍然都打印为True:{{1}中的实现将被使用。

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

String

答案 1 :(得分:7)

引用Equals的文档:

  

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

== operator

  

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

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

来自documentation

的引用
  

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

答案 2 :(得分:2)

你的想法似乎是Java风格。在java中,==运算符无法自定义,因此对于引用类型,它始终表示引用相等,而它表示基本类型的值相等。另一方面,Equals用于检查引用类型中的值相等。

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

默认情况下,Equals==都会检查引用类型的引用相等性,以及值类型的值相等性。但是,对于string,两者都是自定义的,以检查值的相等性。