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

Jui*_*est 17 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
Run Code Online (Sandbox Code Playgroud)

怎么会这样?两者都是不同的对象引用.假设我们认为这些是参考.但我试着这样使用

string s1 = new string("ab");
string s2 = new string("ab");
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*eet 23

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

string s1 = "a";
string s2 = "a";
Console.WriteLine(s1 == s2);
Run Code Online (Sandbox Code Playgroud)

你声称:

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

由于字符串实习,这不是真的.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
Run Code Online (Sandbox Code Playgroud)

然而,即使这些以不同的对象的引用,==超载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
Run Code Online (Sandbox Code Playgroud)

比较一下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));
Run Code Online (Sandbox Code Playgroud)

...然后编译代码中的两个方法调用都只是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)
Run Code Online (Sandbox Code Playgroud)


Dar*_*rov 7

引用Equals的文档:

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

==运算符:

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

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

文档中引用:

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