Сравнение свойств объектов в [закрытом] c#

Этот ответ отредактирован

Ваш метод настроен на возврат одного Country, но ваш код возвращает IEnumerable<Country>.

Но проблема, похоже, решается по-разному в зависимости от версии .Net. Если вы используете .Net Core 2.2 (или позже в будущем), это должно работать:

public async Task<ActionResult<IEnumerable<Country>>> GetCountryRes()
{
    var x = await ObjRepo.GetCountries();    
    return x;
}
111
задан Yvette Colomb 5 October 2018 в 21:35
поделиться

6 ответов

Я искал фрагмент кода, который делал бы что-то подобное, помогающее при написании модульного теста. Вот что я в итоге использовал.

public static bool PublicInstancePropertiesEqual<T>(T self, T to, params string[] ignore) where T : class 
  {
     if (self != null && to != null)
     {
        Type type = typeof(T);
        List<string> ignoreList = new List<string>(ignore);
        foreach (System.Reflection.PropertyInfo pi in type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
        {
           if (!ignoreList.Contains(pi.Name))
           {
              object selfValue = type.GetProperty(pi.Name).GetValue(self, null);
              object toValue = type.GetProperty(pi.Name).GetValue(to, null);

              if (selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue)))
              {
                 return false;
              }
           }
        }
        return true;
     }
     return self == to;
  }

РЕДАКТИРОВАТЬ:

Тот же код, что и выше, но с использованием методов LINQ и Extension:

public static bool PublicInstancePropertiesEqual<T>(this T self, T to, params string[] ignore) where T : class
{
    if (self != null && to != null)
    {
        var type = typeof(T);
        var ignoreList = new List<string>(ignore);
        var unequalProperties =
            from pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
            where !ignoreList.Contains(pi.Name) && pi.GetUnderlyingType().IsSimpleType() && pi.GetIndexParameters().Length == 0
            let selfValue = type.GetProperty(pi.Name).GetValue(self, null)
            let toValue = type.GetProperty(pi.Name).GetValue(to, null)
            where selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue))
            select selfValue;
        return !unequalProperties.Any();
    }
    return self == to;
}

public static class TypeExtensions
   {
      /// <summary>
      /// Determine whether a type is simple (String, Decimal, DateTime, etc) 
      /// or complex (i.e. custom class with public properties and methods).
      /// </summary>
      /// <see cref="http://stackoverflow.com/questions/2442534/how-to-test-if-type-is-primitive"/>
      public static bool IsSimpleType(
         this Type type)
      {
         return
            type.IsValueType ||
            type.IsPrimitive ||
            new[]
            {
               typeof(String),
               typeof(Decimal),
               typeof(DateTime),
               typeof(DateTimeOffset),
               typeof(TimeSpan),
               typeof(Guid)
            }.Contains(type) ||
            (Convert.GetTypeCode(type) != TypeCode.Object);
      }

      public static Type GetUnderlyingType(this MemberInfo member)
      {
         switch (member.MemberType)
         {
            case MemberTypes.Event:
               return ((EventInfo)member).EventHandlerType;
            case MemberTypes.Field:
               return ((FieldInfo)member).FieldType;
            case MemberTypes.Method:
               return ((MethodInfo)member).ReturnType;
            case MemberTypes.Property:
               return ((PropertyInfo)member).PropertyType;
            default:
               throw new ArgumentException
               (
                  "Input MemberInfo must be if type EventInfo, FieldInfo, MethodInfo, or PropertyInfo"
               );
         }
      }
   }
160
ответ дан 24 November 2019 в 03:00
поделиться

Удостоверьтесь, что объекты не null.

Наличие obj1 и obj2:

if(obj1 == null )
{
   return false;
}
return obj1.Equals( obj2 );
1
ответ дан Rajmond Burgaj 24 November 2019 в 03:00
поделиться

Первая вещь, которую я предложил бы, будет состоять в том, чтобы разделить фактическое сравнение так, чтобы это было более читаемо (я также вынул ToString () - который необходим?):

else {
    object originalProperty = sourceType.GetProperty(pi.Name).GetValue(this, null);
    object comparisonProperty = destinationType.GetProperty(pi.Name).GetValue(comparisonObject, null);

    if (originalProperty != comparisonProperty)
        return false;

следующее предложение состояло бы в том, чтобы минимизировать использование отражения как можно больше - это действительно медленно. Я имею в виду, действительно медленный. Если бы Вы собираетесь сделать это, я предложил бы кэшировать ссылки свойства. Я не глубоко знаком с API Reflection, поэтому если это немного выключено, просто корректируйтесь, чтобы заставить его скомпилировать:

// elsewhere
Dictionary<object, Property[]> lookupDictionary = new Dictionary<object, Property[]>;

Property[] objectProperties = null;
if (lookupDictionary.ContainsKey(sourceType)) {
  objectProperties = lookupProperties[sourceType];
} else {
  // build array of Property references
  PropertyInfo[] sourcePropertyInfos = sourceType.GetProperties();
  Property[] sourceProperties = new Property[sourcePropertyInfos.length];
  for (int i=0; i < sourcePropertyInfos.length; i++) {
    sourceProperties[i] = sourceType.GetProperty(pi.Name);
  }
  // add to cache
  objectProperties = sourceProperties;
  lookupDictionary[object] = sourceProperties;
}

// loop through and compare against the instances

Однако я должен сказать, что соглашаюсь с другими плакатами. Это пахнет ленивым и неэффективным. Необходимо реализовывать IComparable вместо этого :-).

1
ответ дан tsimon 24 November 2019 в 03:00
поделиться

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

Также аннулируют, проверяет параметр также.

, Кроме того, я использовал бы 'var' только для создания кода более читаемым (если его c#3 кодируют)

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

1
ответ дан DarkwingDuck 24 November 2019 в 03:00
поделиться

Вы переопределяете.ToString () на всех Ваших объектах, которые находятся в свойствах? Иначе то второе сравнение могло возвратиться с пустым указателем.

кроме того, в том втором сравнении, я нахожусь на заборе о конструкции! (== B) по сравнению с (A! = B), с точки зрения удобочитаемости годы шести месяцев/двух с этого времени. Сама строка довольно широка, который в порядке, если Вы имеете широкий монитор, но не могли бы распечатать очень хорошо. (придеритесь к мелочам)

, все Ваши объекты всегда с помощью свойств, таким образом, что этот код будет работать? Могли быть некоторые внутренние, неимущие данные, которые могли отличаться от одного объекта до другого, но все выставленные данные являются тем же? Я думаю о некоторых данных, которые могли изменяться со временем, как два генератора случайных чисел, которые, оказывается, поражают то же число однажды, но собираются произвести две различных последовательности информации или просто любые данные, которые не становятся выставленными через интерфейс свойства.

2
ответ дан mmr 24 November 2019 в 03:00
поделиться

Я думаю, что было бы лучше следовать за шаблоном для Переопределения Object#Equals ()
Для лучшего описания: Read Bill Wagner Эффективный C# - Объект 9 я думаю

public override Equals(object obOther)
{
  if (null == obOther)
    return false;
  if (object.ReferenceEquals(this, obOther)
    return true;
  if (this.GetType() != obOther.GetType())
    return false;
  # private method to compare members.
  return CompareMembers(this, obOther as ThisClass);
}
  • Также в методах, которые проверяют на равенство, необходимо возвратить любой TRUE или FALSE. или они равны, или они не.. вместо того, чтобы выдать исключение, возвратите false.
  • я считал бы переопределение Object#Equals.
  • Даже при том, что Вы, должно быть, рассмотрели, это, с помощью Отражения для сравнения свойств, предположительно, медленно (у меня нет чисел для резервного копирования этого). Это - поведение по умолчанию для valueType#Equals в C#, и рекомендуется переопределить, Равняется для типов значения, и сделайте мудрый участник выдерживает сравнение для производительности. (Ранее я считанный из скорости это, поскольку у Вас есть набор пользовательского Свойства, возражает... моему плохому.)

декабрь обновления 2011:

  • , Конечно, если тип уже имеет производство, Равняется () затем, Вам нужен другой подход.
  • при использовании этого для сравнения неизменных структур данных исключительно в тестовых целях, Вы не должны добавлять Равняние производственным классам (Кто-то мог бы полить из шланга тесты chainging, Равняется реализации, или можно предотвратить создание требуемого от производства, Равняется реализации).
6
ответ дан Gishu 24 November 2019 в 03:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: