Когда я сравниваю объект (тип), он использует IEquatable определенного класса? - PullRequest
2 голосов
/ 28 января 2011

Мой метод получает два параметра, оба типа Object.Они имеют тот же тип, который реализует IEquatable.

. Мой вопрос: когда я делаю: param1 == param2 сравнивает каркас с использованием переопределения оператора IEquatable определенного класса или использует * 1007?* который просто сравнивает указатель памяти двух объектов?

Какой лучший способ сделать это?Есть ли с дженериками и деривационными ограничениями?

Ответы [ 3 ]

4 голосов
/ 28 января 2011

На самом деле, это не так.Оператор == по умолчанию будет проверять на равенство ссылок, независимо от переопределенного поведения вашего метода Equals (если вы его переопределили, что вам, безусловно, следует иметь, если вы реализовали IEquatable<T>).

То есть, если ваши переменные набраны как object, но вы хотите использовать собственное сравнение на равенство, используйте Equals(x, y) вместо x == y.

Тогда, даже если вы реализовалиIEquatable<T>, обязательно по-прежнему переопределяйте object.Equals, например:

class MyType : IEquatable<MyType>
{
    public bool Equals(MyType other)
    {
        // Whatever you want.
    }

    public override bool Equals(object other)
    {
        // Presumably you check for null above.
        return Equals(other as MyType);
    }
}

Хотя вы, конечно, можете также перегружать == и != операторы для вашего типа, это ничего не даст, если у вас есть ссылки на объекты этого типа, которые являются просто object переменными, например:

object x = new MyType();
object y = new MyType();
Console.WriteLine(Equals(x, y));
Console.WriteLine(x == y);

Выше не будет работать, как вы могли быожидайте (если вы перегружены == и ожидаете, что это будет использоваться), потому что перегрузка == должна быть разрешена во время компиляции;поскольку x и y вводятся как произвольные объекты, компилятор C # выберет оператор == типа object, который, опять же, просто проверяет равенство ссылок.


Обновление : Теперь вы можете убедиться, что ваш оператор == используется, если ваши переменные введены в виде класса, в котором вы определили его или более производного типа.Например, для следующих типов:

class A
{
    public static bool operator ==(A x, A y) { return true; }
    public static bool operator !=(A x, A b) { return false; }
}

class B : A { }

class AComparer<T> where T : A
{
    public bool CompareEqual(T x, T y) { return x == y; }
}

Приведенный выше метод AComparer<T>.CompareEqual будет использовать ваш перегруженный оператор == для любого типа T, производного от A.

Главное, что нужно помнить, это то, что == равен static , что означает, что его разрешение перегрузки выполняется во время компиляции, а не во время выполнения с использованием vtable (если вы не используетеdynamic, но это совсем другой зверь).Так что просто помните об этом всякий раз, когда вы используете в коде оператор ==, и вы хотите, чтобы перегрузка перешла к перестановке вашего пользовательского типа.

2 голосов
/ 28 января 2011

Вы также должны переопределить Equals, и даже GetHashCode (): посмотрите здесь: http://blogs.msdn.com/b/jaredpar/archive/2009/01/15/if-you-implement-iequatable-t-you-still-must-override-object-s-equals-and-gethashcode.aspx

1 голос
/ 28 января 2011

Если параметры вашего метода определены как object, то выполнение param1 == param2 просто выполняет равенство ссылок, поскольку оператор == не является полиморфным.

...