我试图查看在 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 和重载的 == 运算符之间出现了无限循环(正如预期的那样) .字符串类有什么不同还是我的 Reflector 正在报告
static Equals(object o1, object o2)
将 Object 类作为 String 类的一部分的方法?
最佳答案
C# 中的相等运算符不是多态的。当你评估 objA == objB
,你实际上是在执行 ==(object a, object b)
运算符实现(检查引用相等性),而不是 ==(string a, string b)
,因为 objA
的声明类型和 objB
变量是 object
, 不是 string
.
您在代码中可能犯的错误是您没有将类实例转换为 object
在评估 ==
之前运算符(operator)。
假设您有:
public static bool Equals(MyClass objA, MyClass objB)
{
return objA == objB || objA != null && objB != null && objA.Equals(objB);
}
...您需要将其替换为:
public static bool Equals(MyClass objA, MyClass objB)
{
return (object)objA == (object)objB || objA != null && objB != null && objA.Equals(objB);
}
…相当于:
public static bool Equals(MyClass objA, MyClass objB)
{
return object.ReferenceEquals(objA, objB) || objA != null && objB != null && objA.Equals(objB);
}
更新: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 代码的前几行实际上是:
ldarg.0
ldarg.1
bne.un.s IL_0006
ldc.i4.1
ret
bne.un.s
定义为“如果两个无符号整数值不相等(无符号值),则在指定偏移处分支到目标指令,缩写形式。”
因此,看来毕竟是在执行引用相等。
关于c# - c# 中的字符串相等运算符 ==,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9317737/