Не работает сравнение объектов по полям C#

119
20 августа 2019, 22:30
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ObjectEqualsTest
{
    public class Point
    {
        public Int32 x, y;
        public Point(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
        public override bool Equals(object obj)
        {
            if (obj.GetType()!= this.GetType())
                return false;
            FieldInfo[] thisFieldsInfo = this.GetType().GetFields();
            FieldInfo[] objFieldsInfo = obj.GetType().GetFields();
            if (thisFieldsInfo.Length != objFieldsInfo.Length)
                return false;
            else
            {
                for (int i = 0; i < thisFieldsInfo.Length; i++)
                {
                    if ((thisFieldsInfo[i].GetType() != objFieldsInfo[i].GetType()) &&
                      (thisFieldsInfo[i].Name != objFieldsInfo[i].Name)&& 
                        (thisFieldsInfo[i].GetValue(this) != objFieldsInfo[i].GetValue(obj)))
                    {
                        Console.WriteLine(thisFieldsInfo[i].GetValue(this) + " " + objFieldsInfo[i].GetValue(obj));
                        return false;
                    }
                    else
                    {
                        Console.WriteLine(thisFieldsInfo[i].GetValue(this) + " " + objFieldsInfo[i].GetValue(obj));
                        if (i == thisFieldsInfo.Length - 1)
                            return true;
                    }
                }
            }
            return false;
        }
        public override int GetHashCode()
        {
            var hashCode = 1502939027;
            hashCode = hashCode * -1521134295 + x.GetHashCode();
            hashCode = hashCode * -1521134295 + y.GetHashCode();
            return hashCode;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Point x1 = new Point(1, 3);
            Point x2 = new Point(1, 2);
            Console.WriteLine(x1.Equals(x2));
            Console.ReadKey();
        }
    }
}

Есть вот такой код для сравнения двух объектов. Проблема в том, что if() с проверками на тип, имя и значение полей работает как-то неадекватно. Если закомментировать первые две проверки - всегда выдаёт false, если разкомментирую первую и вторую проверки - всегда будет true, но ведь проверка значения выдаёт false, wtf. Не могу понять, что я не так делаю.

Answer 1

Во-первых, Вы хотели поставить не И, a ИЛИ:

if ((thisFieldsInfo[i].GetType() != objFieldsInfo[i].GetType()) ||
    (thisFieldsInfo[i].Name != objFieldsInfo[i].Name) || 
    (thisFieldsInfo[i].GetValue(this) != objFieldsInfo[i].GetValue(obj)))

Во-вторых, thisFieldsInfo[i].GetType() и objFieldsInfo[i].GetType() возвращают тип FieldInfo - эта проверка бессмысленна.

В-третьих, .GetValue возвращает object, в который завернуто целое значение. Сравнение двух объектов происходит по их ссылкам - для разных объектов ссылки всегда разные.

public override bool Equals(object obj)
{
  if (!(obj is Point))
    return false;
  Point p = (Point)obj;
  return p.x == x && p.y == y;
}
public override bool Equals(object obj)
{
  if (obj.GetType() != this.GetType())
    return false;
  FieldInfo[] fields = this.GetType().GetFields();
  for (int i = 0; i < fields.Length; i++)
  {
    // need to check reference fields for null
    if (!fields[i].GetValue(this).Equals(fields[i].GetValue(obj)))
      return false;
  }
  return true;
}
READ ALSO
Правильно ли я сделал таймер?

Правильно ли я сделал таймер?

Часы, минуты и секунды задаю с инспектораМне не нужен сверхточный таймер, но принцип правильный? А может есть какие-нибудь более легкие способы,...

117
Персонаж должен тащить обьект [закрыт]

Персонаж должен тащить обьект [закрыт]

подскажите как это реализовать:Персонаж должен тащить объектВ инете искал ничего не нашел

118
MVVM Получить View в View Model

MVVM Получить View в View Model

У меня имеется окно авторизации: TextBox для логина, PasswordBox для пароля и кнопочка - ВойтиПосле того как пользователь вводит данные мне нужно проверить...

138
Как просто работать с / открыть / изменить / сохранить Excel - xlsx / CSV файлы

Как просто работать с / открыть / изменить / сохранить Excel - xlsx / CSV файлы

Сколько я ни искал, всё как-то уж больно сложно и избыточно функционально

140