Это то, что я придумал в качестве метода для класса, унаследованного от многих других моих классов. Идея состоит в том, что он позволяет просто сравнивать свойства объектов одного типа.
Теперь это действительно работает, но в интересах повышения качества моего кода я подумал, что брошу его для проверки. Как это может быть лучше / эффективнее / и т. Д.?
/// <summary>
/// Compare property values (as strings)
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public bool PropertiesEqual(object comparisonObject)
{
Type sourceType = this.GetType();
Type destinationType = comparisonObject.GetType();
if (sourceType == destinationType)
{
PropertyInfo[] sourceProperties = sourceType.GetProperties();
foreach (PropertyInfo pi in sourceProperties)
{
if ((sourceType.GetProperty(pi.Name).GetValue(this, null) == null && destinationType.GetProperty(pi.Name).GetValue(comparisonObject, null) == null))
{
// if both are null, don't try to compare (throws exception)
}
else if (!(sourceType.GetProperty(pi.Name).GetValue(this, null).ToString() == destinationType.GetProperty(pi.Name).GetValue(comparisonObject, null).ToString()))
{
// only need one property to be different to fail Equals.
return false;
}
}
}
else
{
throw new ArgumentException("Comparison object must be of the same type.","comparisonObject");
}
return true;
}
c#
object
properties
comparison
гвоздь
источник
источник
Ответы:
Я искал фрагмент кода, который делал бы что-то подобное, чтобы помочь с написанием модульного теста. Вот что я в итоге использовал.
РЕДАКТИРОВАТЬ:
Тот же код, что и выше, но использует методы LINQ и Extension:
источник
ОБНОВЛЕНИЕ: последняя версия Compare-Net-Objects находится на GitHub , имеет пакет NuGet и руководство . Это можно назвать
Или, если вам нужно изменить конфигурацию, используйте
Полный список настраиваемых параметров находится в ComparisonConfig.cs
Оригинальный ответ:
Ограничения, которые я вижу в вашем коде:
Самый большой из них заключается в том, что он не выполняет глубокого сравнения объектов.
Он не выполняет сравнение элементов по элементам, если свойства являются списками или содержат списки в виде элементов (это может быть n уровней).
При этом не учитывается, что некоторые типы свойств не должны сравниваться (например, свойство Func, используемое для целей фильтрации, например, свойство в классе PagedCollectionView).
Он не отслеживает, какие свойства на самом деле были разными (чтобы вы могли показать их в своих утверждениях).
Сегодня я искал какое-то решение для модульного тестирования, чтобы провести глубокое сравнение свойств, и в итоге я использовал: http://comparenetobjects.codeplex.com .
Это бесплатная библиотека с одним классом, который вы можете просто использовать следующим образом:
Кроме того, его можно легко перекомпилировать для Silverlight. Просто скопируйте один класс в проект Silverlight и удалите одну или две строки кода для сравнений, которые недоступны в Silverlight, например, сравнение частных членов.
источник
IgnoreObjectTypes
настройка может быть полезна при наличии разных типов.DifferencesString
исключен из класса CompareObjects. Но теперь вы можете получить это из ComparisonResult:var r = compareObjects.Compare(objectA, objectB); Assert.IsTrue(r.AreEqual, r.DifferencesString);
Я думаю, что было бы лучше следовать шаблону для Override Object # Equals ().
Для лучшего описания: прочтите Эффективный C # Билла Вагнера - пункт 9, я думаю
Обновление - декабрь 2011 г .:
источник
Если производительность не имеет значения, вы можете сериализовать их и сравнить результаты:
источник
Я думаю, что ответ Big T был неплохим, но подробного сравнения не было, поэтому я немного его изменил:
источник
Я бы добавил следующую строку в метод PublicInstancePropertiesEqual, чтобы избежать ошибок копирования и вставки:
источник
Вы переопределяете .ToString () для всех ваших объектов, находящихся в свойствах? В противном случае это второе сравнение может вернуться с нулевым значением.
Кроме того, во втором сравнении я сомневаюсь в конструкции! (A == B) по сравнению с (A! = B) с точки зрения удобочитаемости через шесть месяцев / два года. Сама линия довольно широкая, что нормально, если у вас широкий монитор, но может не печатать очень хорошо. (придирка)
Все ли ваши объекты всегда используют свойства, чтобы этот код работал? Могут ли быть какие-то внутренние, не относящиеся к собственности данные, которые могут отличаться от одного объекта к другому, но все открытые данные одинаковы? Я думаю о некоторых данных, которые могут меняться со временем, например, о двух генераторах случайных чисел, которые случайно попадают в одно и то же число в один момент, но собираются произвести две разные последовательности информации или просто любые данные, которые не раскрываются. через интерфейс свойств.
источник
Если вы сравниваете только объекты одного типа или ниже по цепочке наследования, почему бы не указать параметр в качестве базового типа, а не объекта?
Также выполните нулевые проверки параметра.
Кроме того, я бы использовал var, чтобы сделать код более читабельным (если это код С # 3)
Кроме того, если объект имеет ссылочные типы в качестве свойств, тогда вы просто вызываете для них ToString (), который на самом деле не сравнивает значения. Если ToString не перезаписан, он просто вернет имя типа в виде строки, которая может возвращать ложные срабатывания.
источник
Первое, что я бы предложил, - это разделить фактическое сравнение, чтобы оно было более читабельным (я также убрал ToString () - это нужно?):
Следующее предложение - как можно меньше использовать отражение - это очень медленно. Я имею в виду, очень медленно. Если вы собираетесь это сделать, я бы посоветовал кэшировать ссылки на свойства. Я не очень хорошо знаком с Reflection API, поэтому, если это немного не так, просто настройте его, чтобы он скомпилировался:
Однако я должен сказать, что согласен с другими плакатами. Это пахнет ленивым и неэффективным. Вместо этого вы должны реализовать IComparable :-).
источник
здесь пересмотренный для обработки null = null как равного
источник
В итоге я сделал это:
Использование:
Обновить
Если вы хотите игнорировать некоторые свойства по имени:
Использование:
источник
Вы можете оптимизировать свой код, вызывая GetProperties только один раз для каждого типа:
источник
Для полноты я хочу добавить ссылку на http://www.cyotek.com/blog/comparing-the-properties-of-two-objects-via-reflection Он имеет более полную логику, чем большинство других ответов на этой странице.
Однако я предпочитаю Compare-Net-объектов библиотеки https://github.com/GregFinzer/Compare-Net-Objects (далее по Ливиу Trifoi «s ответ )
Библиотека имеет пакет NuGet http://www.nuget.org/packages/ CompareNETObjects и несколько параметров для настройки.
источник
Убедитесь, что предметов нет
null
.Имея
obj1
иobj2
:источник
Это работает, даже если объекты разные. вы можете настроить методы в классе утилит, возможно, вы также захотите сравнить частные свойства ...
источник
Обновление ответа Ливиу выше - CompareObjects.DifferencesString устарело.
Это хорошо работает в модульном тесте:
источник
Assert.IsTrue(result.AreEqual, result.DifferencesString);
Этот метод получит
properties
из класса и сравнит значения для каждогоproperty
. Если какие-либо значения отличаются, будетreturn false
, иначе будетreturn true
.Использование:
bool isEqual = Compare<Employee>(Object1, Object2)
источник
Чтобы расширить ответ @nawfal: s, я использую его для тестирования объектов разных типов в своих модульных тестах для сравнения одинаковых имен свойств. В моем случае объект базы данных и DTO.
Используется так в моем тесте;
источник
иногда вы не хотите сравнивать все общедоступные свойства и хотите сравнить только их подмножество, поэтому в этом случае вы можете просто переместить логику, чтобы сравнить желаемый список свойств с абстрактным классом
и позже используйте этот абстрактный класс для сравнения объектов
источник
мое решение вдохновлено ответом Араса Аленина выше, где я добавил один уровень сравнения объектов и настраиваемый объект для результатов сравнения. Мне также интересно получить имя свойства с именем объекта:
Использование следующего класса для хранения результатов сравнения
И образец модульного теста:
источник