4

我认为值类型(结构)中“Equals”的默认行为是使用反射来比较两个值的内容,因此如果性能很重要,建议覆盖 Equals 运算符以提高效率。

但似乎 Equals 的签名是:

public override bool Equals( object ob )

这意味着即使我将覆盖此方法,当我比较值类型时,我仍然会有装箱,因为参数必须是“对象”类型。

我对么 ?拳击会发生吗?我应该只对值类型使用 == 运算符吗?

编辑:还有一个小问题,为什么当我覆盖==时它应该是静态的并获得2个参数,而不是更直观的非静态形式并将“this”与一个参数进行比较?

4

1 回答 1

8

除了覆盖Object.Equals()你应该实现IEquatable<T>T你的类型本身在哪里。 IEquatable<T>.Equals()接受类型的参数T

如果您隐式实现接口(为什么不实现?),那么T将尽可能使用接受 -typed 参数的更具体的方法,在这种情况下不会发生装箱。(如果您重载Equals()并且不实现接口,这是正确的,但在这种情况下没有理由不实现接口。)

这是我在实现值类型相等时通常使用的模式:

struct Foo : IEquatable<Foo>
{
    public bool Equals(Foo other)
    {
        // Do your equality test here.
        throw new NotImplementedException();
    }

    public override bool Equals(object other)
    {
        if (other != null && other is Foo) {
            return Equals((Foo)other);
        }

        return false;
    }

    // If you also want to overload the equality operator:
    public static bool operator==(Foo a, Foo b)
    {
        return a.Equals(b);
    }

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

当然,也不要忘记覆盖Object.GetHashCode()


请注意,使用该Equals(object)方法时,只有参数被装箱。您正在调用的对象不会被装箱,除非您object先将其转换为(或接口类型)。ldloca将为您调用的对象发出、ldflda或指令之一ldsflda(视情况而定),而另一个将被装箱(在没有更具体的重载的情况下)。

于 2013-03-22T19:01:02.197 回答