C# 中的字符串相等运算符 ==
我试图查看 C# 中字符串类中比较运算符实现的代码。发现的是这样的:
//THIS IS NOT WHAT I MEANT
public static bool Equals(object objA, object objB)
{
return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB)));
}
//THIS IS WHAT I SEE REALLY and the above is what I would expect to see
public static bool Equals(string a, string b)
{
return ((a == b) || (((a != null) && (b != null)) && EqualsHelper(a, b)));
}
public static bool operator ==(string a, string b)
{
return Equals(a, b);
}
我不知道是否是 Reflector 在欺骗我,但是当我尝试为我自己的类实现这个策略时,我在 Equals 和重载的 == 运算符之间出现了无限循环(如预期的)。字符串类中是否有什么不同,或者是我的反射器将
static Equals(object o1, object o2)
对象类上的方法报告为字符串类的一部分?
I have tried to peek into the code implemented for comparison operator in string class in C#. What found was this:
//THIS IS NOT WHAT I MEANT
public static bool Equals(object objA, object objB)
{
return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB)));
}
//THIS IS WHAT I SEE REALLY and the above is what I would expect to see
public static bool Equals(string a, string b)
{
return ((a == b) || (((a != null) && (b != null)) && EqualsHelper(a, b)));
}
public static bool operator ==(string a, string b)
{
return Equals(a, b);
}
I don't know whether it is the Reflector that is playing tricks on me, but when I tried to implement this strategy for my own class, I got an infinite loop between Equals and the overloaded == operator (as expected). Is there sth different in string class or is it my Reflector that is reporting
static Equals(object o1, object o2)
method on the Object class to be part of String class?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
C# 中的相等运算符不是多态的。当您计算 objA == objB 时,您实际上执行的是 ==(object a, object b) 运算符实现(检查引用相等性),而不是执行>==(string a, string b),因为
objA
和objB
变量的声明类型是object
,而不是字符串
。您在代码中可能犯的错误是,在对类实例评估
==
运算符之前,您没有将类实例转换为object
。假设您有:
...您需要将其替换为:
...这相当于:
更新:
String
类包含两者一个static bool Equals(string a, string b)
方法和一个static bool Equals(object a, object b)
方法。区别在于前者是在String
类本身中定义的,而后者是从Object
类(它是String
的基类)继承的。代码>)。您的反射器可能会也可能不会根据其设置显示继承的方法。在您发布的代码中,由于
objA
和objB
的声明类型是object
,因此带有object
的运算符无论实例的实际类型如何,都会调用参数。更新2:您更新的代码似乎包含无限递归。我认为这可能是反射器工具中的错误。
更新3:这似乎是反汇编中的错误。
Equals(string a, string b)
运算符实现中的第一个条件在反汇编的 C# 代码中显示为a == b
。然而,IL 代码的前几行实际上是:bne.un.s
被定义为“如果两个无符号整数值不相等(无符号值),短格式,则分支到指定偏移处的目标指令。”因此,看起来引用相等毕竟正在执行。
Equality operators in C# are not polymorphic. When you evaluate
objA == objB
, you are actually executing the==(object a, object b)
operator implementation (which checks for reference equality), not the==(string a, string b)
, because the declared type of theobjA
andobjB
variables isobject
, notstring
.The error you’re probably making in your code is that you’re not casting your class instances to
object
before evaluating the==
operator on them.Assuming you have:
…you would need to replace it with:
…which is equivalent to:
Update: The
String
class contains both astatic bool Equals(string a, string b)
method and astatic bool Equals(object a, object b)
method. The difference is that the former is defined within theString
class itself, whilst the latter is inherited from theObject
class (which is the base class ofString
). Your reflector might or might not display inherited methods based on its settings.In your posted code, since the declared type of
objA
andobjB
isobject
, then the operator with theobject
parameters would get called, irrespective of the instances’ actual type.Update2: Your updated code does appear to contain an infinite recursion. I assume it might be a bug within the reflector tool.
Update3: This does appear to be a bug in the disassember. The first condition in the implementation of the
Equals(string a, string b)
operator is shown, in disassembled C# code, as beinga == b
. However, the first few lines of the IL code are actually:bne.un.s
is defined as “Branch to the target instruction at the specified offset if two unsigned integer values are not equal (unsigned values), short form.”Thus, it appears that reference equality is being performed after all.
没有
String.Equals(object, object)
方法。您正在看到
Object.Equals
。它不递归的原因是
objA == objB
调用内置对象相等运算符,而不是自定义字符串相等运算符。(运算符重载根据操作数的编译时类型来解决)
There is no
String.Equals(object, object)
method.You're seeing
Object.Equals
.The reason it doesn't recurse is that
objA == objB
calls the built-in object equality operator, not the custom string equality operator.(Operator overloads are resolved based on the compile-time type of the operands)
一个不太令人困惑的解决方案:不要使用
==
运算符:A less confusing solution: don't use the
==
operator:它引用的 equals 方法是这样的:
即一个 equals 方法接受两个字符串而不是两个对象。
The equals method it refers to is this:
I.e. an equals method which takes two strings and not two objects.