C # с типами объектов метод Object.Equals (object a, object b) возвращает неверный результат

Мне нужно проверить объект (не все свойства), с примитивными типами все работает правильно, но с типами объектов метод Object.Equals(object a, object b) возвращает неправильный результат.

        public static bool IsModified<T>(T newProp, T oldProp) where T : class
    {
        List<string> IgnoreProps = new List<string> { "UpdatedOn", "UpdatedById", "UpdatedBy", "RowVersion" };

        Type type = typeof(T);
        foreach(PropertyInfo prop in type.GetProperties())
        {
            if (IgnoreProps.Contains(prop.Name))
            {
                continue;
            }

            var propType = prop.PropertyType;

            var newValue = prop.GetValue(newProp);
            var oldValue = prop.GetValue(oldProp);

            newValue = Convert.ChangeType(newValue, propType);
            oldValue = Convert.ChangeType(oldValue, propType);

            var a = Equals(newValue, oldValue); // return incorrect value

            if (!Equals(newValue, oldValue))
            {
                return true;
            }
        }

        return false;
    }

Первый объект

введите описание изображения здесь

Второй объект

введите описание изображения здесь


person Espi4U    schedule 01.09.2020    source источник
comment
Не добавляйте к вопросу релевантную информацию в виде изображений, пожалуйста, добавляйте значения в виде текста. Также ваш тип переопределяет метод Equals?   -  person Ackdari    schedule 01.09.2020


Ответы (2)


Реализация Equals по умолчанию поддерживает ссылочное равенство для ссылочных типов и побитовое равенство для типов значений. Равенство ссылок означает, что сравниваемые ссылки на объекты относятся к одному и тому же объекту. Побитовое равенство означает, что сравниваемые объекты имеют одинаковое двоичное представление. (https://docs.microsoft.com/en-us/dotnet/api/system.object.equals?redirectedfrom=MSDN&view=netcore-3.1)

Поскольку у вас есть две разные ссылки (var newValue, var oldValue), вы получите false.

person Roman Ryzhiy    schedule 01.09.2020

Представьте, что у вас есть класс MyCustomClass и следующий пример:

class MyCustomClass
{
    public string txt;
}

static void Main(string[] args)
{
    MyCustomClass cl1 = new MyCustomClass()
    {
        txt = "a"
    };
    MyCustomClass cl2 = new MyCustomClass()
    {
        txt = "a"
    };

    if (Equals(cl1, cl2))
        Console.WriteLine("equal");
    else
        Console.WriteLine("NOT equal");
}

Если вы запустите приведенный выше код, вы получите результат NOT equal. Это потому, что .net попытается сравнить только ссылки между двумя экземплярами класса. например, если вы напишете:

    if (Equals(cl1, cl1))
        Console.WriteLine("equal");
    else
        Console.WriteLine("NOT equal");

это приведет к equal при сравнении того же экземпляра cl1 с cl1.

Для вас, чтобы проводить сравнения с методом Equals, вам придется перезаписать его в своем классе. Например, ваш класс должен стать:

class MyCustomClass
{
    public string txt;

    public override bool Equals(object obj)
    {
        //Check for null and compare run-time types.
        if ((obj == null) || !this.GetType().Equals(obj.GetType()))
        {
            return false;
        }
        else
        {
            MyCustomClass p = (MyCustomClass)obj;
            return (txt == p.txt);
        }
    }
}

Вышеупомянутый метод Equals не только гарантирует, что сравниваемым объектом является not null, а также same type, но он также гарантирует, что он сравнивает все их поля одно за другим.

person Efthymios Kalyviotis    schedule 01.09.2020