C# 为什么字符串数据类型总是执行值比较

C# 为什么字符串数据类型总是执行值比较,c#,.net,string,C#,.net,String,我在寻找C中==和.Equals方法之间的差异,发现第一个方法比较对象引用,第二个方法比较对象值,除了字符串数据类型==和.Equals都进行内容比较。我真的找不到解释,是因为字符串数据类型是不可变的吗 这是我想说的 object obj1 = "Test"; object obj2 = new string("Test".ToCharArray()); Console.WriteLine(obj1.Equals(obj2) + " " + (obj1 == obj2)); string a

我在寻找C中==和.Equals方法之间的差异,发现第一个方法比较对象引用,第二个方法比较对象值,除了字符串数据类型==和.Equals都进行内容比较。我真的找不到解释,是因为字符串数据类型是不可变的吗

这是我想说的

object obj1 = "Test";
object obj2 = new string("Test".ToCharArray());
Console.WriteLine(obj1.Equals(obj2) + " " + (obj1 == obj2));

string a = "Test";
string b = "Test";
Console.WriteLine(a.Equals(b) + " "+ (a == b));
输出

True False
True True

事实上,在第一次比较中,我们有两个不同的对象具有相同的值,结果为True和false,但是对于string,我们对这两个比较都有True,任何对象都可以覆盖/重载Equals或==,因此它们可以按照库作者希望它们的行为进行操作。

这根本不是真的。==是可重写的运算符,而Equals是可重写的方法。由类定义它们各自的行为方式

也许你把C和Java搞混了

如果要进行引用比较,请使用object.ReferenceEquals。其他一切都取决于实现,但请注意,运算符重写是静态检查的,因此,例如objectsomeString==objectsomeOtherString将进行引用比较,而不是值比较;Equals没有这个问题

大多数情况下,==和Equals都被设计为给出相同的答案,尽管==在比较中总是对类型更严格,如前所述。这适用于双精度结构,其中引用比较实际上没有多大意义

当然,编译器实际上并不做任何检查。如果需要,我可以重写==运算符以始终返回false。或者只检查某个ID是否相等。或者,如果你感觉特别邪恶,就改变被比较的对象。最后,它只是一个静态方法,与其他方法一样,有一些限制

编辑:

为了直接处理您的编辑,字符串始终执行内容比较,因为它的==和等于都被重写以执行内容比较。但是,这并不意味着它总是执行代价高昂的逐字符比较—如果您看看string.Equals是如何实际实现的,您可以看到它尝试了一些方法来避免代价高昂的比较:

如果字符串为null,则它们必须不同 如果两个字符串引用相等,则它们的内容也必须相等 如果两个字符串的长度不相同,则它们必须不同
您可以在这里看到实际的按值比较方法—一段简单的不安全代码,但仍然是手动编写的代码。NET中没有自动的值比较,尽管有一些技巧可以接近。

这是因为它有意义

Java不能这样做,因为它没有运算符重载,但这在C中不是参数


顺便说一句,这不是字符串所独有的。任何类型都可以重载==运算符来执行类似的操作。

你是说如果我创建一个具有10个属性的类,Equals将自动将这10个属性与我的类的另一个实例进行比较?@Joe如果你以给定的方式编写任何东西,它将希望按照你告诉它的方式进行:我只是想从OP中得到一个澄清。他们的假设是从哪里来的还不清楚。顺便说一句。。。不要假设字符串a和字符串b是单独的对象。因为它们是编译时字符串文字,所以它们可能被优化为相同的对象,因此它们是相同的引用。显然,可以关闭此选项。因此,a==b可能是成功的,因为它是相同的引用,而不是内容比较。这里缺少的唯一相关事实是,如果未实现,则==和Equals的默认行为是对引用类型使用引用比较,对结构的所有字段使用位比较。这也是一个惯例,一个类型对于==和Equals应该具有相同的语义,因此如果一个被重写,那么另一个应该是,并且它们的行为应该彼此一致。好的,谢谢我得到它,因为string对象==运算符和Equals都被重写以执行相同的操作comparison@MoezRebai当然它非常简单-返回字符串。Equalsa,b;: