Есть ли лучший способ выполнить Equals для объекта с большим количеством полей? - PullRequest
2 голосов
/ 02 декабря 2009

см. Также Как быстро проверить, если данные Передача два объекта имеют равные свойства в C #?

У меня есть много объектов передачи данных (DTO), каждый из которых содержит множество простых полей . Мне нужно реализовать Equals на всех них (чтобы я мог написать несколько тестов модулей для их транспортировки, var WCF).

Код, который я использую:

public override bool Equals(object rhs)
{

    RequestArguments other = rhs as RequestArguments;

    return
       other != null && 
       other.m_RequestId.Equals(RequestId) && 
       other.m_Type.Equals(m_Type) && 
       other.m_Parameters.Equals(m_Parameters) && 
       other.m_user.Equals(m_user);
}

Должен быть лучший способ! ... (перечисление всех полей скорее вызывает ошибки и проблемы с обслуживанием)

например. У нас есть Объект. MemberwiseClone (), чтобы помочь с делом Cloning (), но я не могу найти ничего, чтобы помочь с Equals. Мы работаем в полном доверии, поэтому решение на основе рефлексии - один из ответов, но я не буду изобретать велосипед.

(Извините, мы не генерируем DTO из предметно-ориентированного языка, в противном случае это будет просто! Также я не могу изменить систему сборки, чтобы добавить еще один шаг)

Ответы [ 4 ]

3 голосов
/ 02 декабря 2009

Забавно, что вы должны спросить, я недавно опубликовал код для выполнения именно этого. Проверьте мой MemberwiseEqualityComparer , чтобы увидеть, соответствует ли он вашим потребностям.

Это действительно удобно и довольно эффективно. Он использует IL-emit для генерации всей функции Equals и GetHashCode при первом запуске (один раз для каждого используемого типа). Он будет сравнивать каждое поле (частное или общедоступное) данного объекта с помощью средства сравнения по умолчанию для этого типа (EqualityComparer.Default). Некоторое время мы использовали его в производстве, и он кажется стабильным, но я не оставлю никаких гарантий =)

Он заботится обо всех тех крайних случаях, о которых вы редко думаете, когда вы катите свой собственный метод equals (то есть вы не можете сравнить свой собственный объект с нулем, если вы сначала не поместили его в объект и многие другие вопросы, связанные с нулями).

Я намеревался написать в блоге об этом, но еще не дошел до этого. Код немного недокументирован, но если вам понравится, я могу немного его почистить.

public override int GetHashCode()
{
    return MemberwiseEqualityComparer<Foo>.Default.GetHashCode(this);
}

public override bool Equals(object obj)
{
    if (obj == null)
        return false;

    return Equals(obj as Foo);
}

public override bool Equals(Foo other)
{
    return MemberwiseEqualityComparer<Foo>.Default.Equals(this, other);
}

MemberwiseEqualityComparer выпускается под лицензией MIT , что означает, что вы можете делать с ним практически все, что захотите, в том числе использовать его в проприетарных решениях, не меняя лицензию.

1 голос
/ 02 декабря 2009

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

РЕДАКТИРОВАТЬ : Вот простой пример сравнения объектов с использованием отражения, он смотрит на свойства вместо полей, но вы понимаете: http://www.willasrari.com/blog/use-systemreflection-for-comparing-custom-objects/000257.aspx

0 голосов
/ 02 декабря 2009

Редактировать : извините, я не заметил, что вы запрашиваете сериализацию. Так что этот подход определенно не работает для вас.


Есть еще один "грязный" способ. Если ваш объект в любом случае сериализуем, вы можете сериализовать их и сравнить полученные потоки.

Это довольно медленно, но должно быть достаточно надежным и простым в реализации.

Мы делаем это иногда, чтобы проверить, изменил ли кто-нибудь какие-либо данные в редакторе.

0 голосов
/ 02 декабря 2009

У вас может быть понятие хеша объекта - всякий раз, когда объект изменяется, вы платите цену за обновление хеша (где хеш буквально является хешем всех объединенных свойств). Затем, если у вас есть куча объектов, которые редко меняются, сравнить их действительно дешево. Цена, конечно, затем оплачивается во время редактирования объекта.

...