为什么字符串数据类型总是执行值比较
本文关键字:执行 比较 字符串 数据类型 为什么 | 更新日期: 2023-09-27 18:17:56
我在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,但对于字符串的情况,我们对两个比较都有 true
这根本不是真的。 ==
是可重写的运算符,Equals
是可重写的方法。由类来定义它们中的每一个的行为方式。
也许您将 C# 与 Java 混淆了?
如果要进行引用比较,请使用 object.ReferenceEquals
。其他一切都取决于实现(但请注意,运算符覆盖是静态检查的,因此例如 (object)someString == (object)someOtherString
将进行参考比较,而不是值比较; Equals
没有这个"问题"(。
大多数情况下,==
和Equals
都旨在给出相同的答案(尽管==
对比较中的类型总是更严格,如前所述(。这适用于双倍的struct
,其中参考比较无论如何都没有多大意义。
当然,编译器实际上并不进行任何检查。如果需要,我可以覆盖 ==
运算符以始终返回 false
.或者只检查某些 ID 是否相等。或者改变被比较的对象,如果你觉得特别邪恶。最后,它只是像其他任何方法一样的静态方法(有一些限制(。
编辑:
为了直接处理您的编辑,string
始终执行内容比较,因为其==
和Equals
都被覆盖以执行内容比较。但是,这并不意味着它总是执行昂贵的逐个字符比较 - 如果您查看string.Equals
的实际实现方式,您会发现它尝试了一些方法来避免昂贵的比较:
- 如果字符串为 null,则它们必须不同
- 如果两个字符串的引用相等,则它们也必须是内容相等的
- 如果两个字符串的长度不同,则它们必须不同
您可以在此处查看实际的按值比较方法 - http://referencesource.microsoft.com/#mscorlib/system/string.cs,11648d2d83718c5e 一段简单的不安全代码,但仍然是手动编写的代码。.NET 中没有自动值比较(尽管有一些技巧很接近(。
这是因为它有意义。
Java不能这样做,因为它没有运算符重载,但这在C#中没有参数。
顺便说一下,这不是字符串独有的。任何类型都可能使==
运算符重载以执行类似操作。
任何对象都可以覆盖/重载Equals
或==
,因此它们可以按照库作者希望它们的行为方式运行。