C#中的字符串相等运算符== [英] String Equality operator == in c#

查看:92
本文介绍了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);
}

我不知道反射器是否在骗我,但是当我尝试为自己的班级实施这种策略时,我在Equals和重载的==运算符之间遇到了无限循环(如预期的那样) .字符串类有什么不同吗?还是我的Reflector正在报告

static Equals(object o1, object o2)

Object类上的方法成为String类的一部分?

解决方案

C#中的等号运算符不是多态的.评估objA == objB时,实际上是在执行==(object a, object b)运算符实现(用于检查引用是否相等),而不是==(string a, string b),因为objAobjB变量的声明类型为object,不是string.

您可能在代码中犯的错误是,您没有在评估类实例上的==运算符之前将其转换为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)方法,以及.区别在于,前者是在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 被定义为分支如果两个无符号整数值不相等(无符号值),则以指定的偏移量移至目标指令的指定位置."

因此,看来引用的相等毕竟是在执行的.

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?

解决方案

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.

这篇关于C#中的字符串相等运算符==的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆