C# 中的字符串相等运算符 ==

发布于 2025-01-06 07:48:01 字数 758 浏览 1 评论 0原文

我试图查看 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

明媚如初 2025-01-13 07:48:01

C# 中的相等运算符不是多态的。当您计算 objA == objB 时,您实际上执行的是 ==(object a, object b) 运算符实现(检查引用相等性),而不是执行>==(string a, string b),因为objAobjB变量的声明类型是object,而不是字符串

您在代码中可能犯的错误是,在对类实例评估 == 运算符之前,您没有将类实例转换为 object

假设您有:

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 的基类)继承的。代码>)。您的反射器可能会也可能不会根据其设置显示继承的方法。

在您发布的代码中,由于 objAobjB 的声明类型是 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 被定义为“如果两个无符号整数值不相等(无符号值),短格式,则分支到指定偏移处的目标指令。”

因此,看起来引用相等毕竟正在执行。

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 the objA and objB variables is object, not string.

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:

public static bool Equals(MyClass objA, MyClass objB)
{
    return objA == objB || objA != null && objB != null && objA.Equals(objB);
}

…you would need to replace it with:

public static bool Equals(MyClass objA, MyClass objB)
{
    return (object)objA == (object)objB || objA != null && objB != null && objA.Equals(objB);
}

…which is equivalent to:

public static bool Equals(MyClass objA, MyClass objB)
{
    return object.ReferenceEquals(objA, objB) || objA != null && objB != null && objA.Equals(objB);
}

Update: The String class contains both a static bool Equals(string a, string b) method and a static bool Equals(object a, object b) method. The difference is that the former is defined within the String class itself, whilst the latter is inherited from the Object class (which is the base class of String). Your reflector might or might not display inherited methods based on its settings.

In your posted code, since the declared type of objA and objB is object, then the operator with the object 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 being a == b. However, the first few lines of the IL code are actually:

ldarg.0
ldarg.1
bne.un.s IL_0006

ldc.i4.1
ret

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.

风启觞 2025-01-13 07:48:01

没有 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)

流云如水 2025-01-13 07:48:01

一个不太令人困惑的解决方案:不要使用 == 运算符:

public static bool Equals(MyClass a, MyClass b) 
{ 
    return ReferenceEquals(a, b)
        || ((!ReferenceEquals(a, null) && !ReferenceEquals(b, null)) && a.Equals(b))); 
} 

A less confusing solution: don't use the == operator:

public static bool Equals(MyClass a, MyClass b) 
{ 
    return ReferenceEquals(a, b)
        || ((!ReferenceEquals(a, null) && !ReferenceEquals(b, null)) && a.Equals(b))); 
} 
热风软妹 2025-01-13 07:48:01

它引用的 equals 方法是这样的:

public static bool Equals(string a, string b)
{
    /* == is the object equals- not the string equals */
    return a == b || (a != null && b != null && string.EqualsHelper(a, b));
}

public static bool operator ==(string a, string b)
{
    return string.Equals(a, b);
}

即一个 equals 方法接受两个字符串而不是两个对象。

The equals method it refers to is this:

public static bool Equals(string a, string b)
{
    /* == is the object equals- not the string equals */
    return a == b || (a != null && b != null && string.EqualsHelper(a, b));
}

public static bool operator ==(string a, string b)
{
    return string.Equals(a, b);
}

I.e. an equals method which takes two strings and not two objects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文