проверка двух экземпляров объекта, чтобы увидеть, совпадают ли они - PullRequest
9 голосов
/ 21 сентября 2010

Мне нужно сравнить два объекта, но сравнить количество их свойств в одном обращении. это не для сортировки, а для подтверждения того, что что-то изменилось; так как один - это старый сохраненный экземпляр, а второй - только что импортированный экземпляр того же самого

Полагаю, лучше всего это написать пользовательский компаратор. Просто я немного сбит с толку относительно того, делать ли IComparer, или IComparable, или что-то в этом роде.

спасибо

физ

Ответы [ 5 ]

9 голосов
/ 21 сентября 2010

Если у вас есть только одно определение равенства для вашего класса, вам не нужно реализовывать какой-либо интерфейс: просто переопределите метод Equals.Однако лучше всего было бы реализовать IEquatable<T> и разумно переопределить GetHashCode (если вы не переопределите хеш-код, равенство будет работать неправильно, когда классы коллекции, методы LINQ и т. Д. Используют егопредварительное условие равенства).Вот пример реализации:

public class Person : IEquatable<Person>
{
    public string Name { get; set; }
    public int Age { get; set; }

    public override int GetHashCode()
    {
        return (Name == null ? 0 : Name.GetHashCode()) ^ Age;
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as Person);
    }

    public bool Equals(Person other)
    {
        return other != null && other.Name == Name && other.Age == Age;
    }
}

Это позволит вам сделать:

Person savedPerson = ...
Person importedPerson = ...

bool hasChanged = !savedPerson.Equals(importedPerson);

Если, с другой стороны, у вас есть много разных определений равенства дляПри других обстоятельствах лучше всего было бы написать различные реализации IEqualityComparer<T>.Вот пример реализации:

public class AgeComparer : IEqualityComparer<Person>
{
    public bool Equals(Person x, Person y)
    {
        return (x == null || y == null) ? x == y : x.Age == y.Age;
    }

    public int GetHashCode(Person obj)
    {
        return obj == null ? 0 : obj.Age;
    }
}  

В этом случае проверка будет выглядеть следующим образом:

Person savedPerson = ...
Person importedPerson = ...
IEqualityComparer<Person> comparer = ...

bool hasChanged = !comparer.Equals(savedPerson, importedPerson);
0 голосов
/ 21 сентября 2010

Это о том, как вы хотите выполнить операцию сравнения. Вы можете выполнить операцию двумя способами:

public void Method()
{
    Foo p1 = new Foo();
    Foo p2 = new Foo();

    p1.CompareTo(p2);
    FooComparer c = new FooComparer();
    c.Compare(p1, p2);
}

class Foo : IComparable
{
    public int CompareTo(object obj)
    {
        throw new NotImplementedException();
    }
}

class FooComparer : IComparer<Foo>
{
    public int Compare(Foo x, Foo y)
    {
        throw new NotImplementedException();
    }
}

Я предпочитаю использовать IComparer для разделения проблем. Фу мой класс, у меня есть некоторые потребности бизнеса. Если я хочу сравнить некоторые Foos, я использую FooComparer. Для вашей ситуации вы можете вернуть количество измененных свойств из метода Compare. Если метод Compare возвращает 0. Тогда два Foos одинаковы.

Как я уже сказал. Это полностью, как вы хотите выполнить действие, я думаю. Перекрывающие операторы равенства также являются хорошим решением. Реализация IEqualityComparer<T> - это еще одно решение.

0 голосов
/ 21 сентября 2010

Альтернативой реализации интерфейса IComparable было бы переопределение функций Equals и GetHashCode.

0 голосов
/ 21 сентября 2010

Как вы уже упоминали, IComparable обычно используется для сортировки.

В этом случае вы захотите перегрузить оператор сравнения: ==

Поскольку обратное сравнение также должно быть допустимым, это означает, что вы также должны перегрузить оператор! =.

Когда вы перегружаете == и! - вы также должны переопределить Equals и GetHashCode.

Достойная книга на C # должна объяснить детали.

0 голосов
/ 21 сентября 2010

Да, вам понадобится ваш тип для реализации IComparable. Здесь - пример того, как это сделать.

...