Переопределение Equals и GetHashCode — реализация по умолчанию в производном классе

#c# #inheritance #equals #gethashcode

#c# #наследование #equals #gethashcode

Вопрос:

Я немного смущен поведением Equals и GetHashCode по умолчанию в C #. Допустим, у меня есть два класса, один из которых является производным от другого:

 public abstract class Question
    {
        public string QuestionText
        {
            get;
            set;
        }

        public override bool Equals(object obj)
        {
            if (obj is Question)
            {
                Question q = (Question)obj;
                return this.QuestionText.Equals(q.QuestionText);
            }
            else
            {
                return false;
            }
        }

        public override int GetHashCode()
        {
            int hash = 13; 
            hash = (hash * 7)   this.QuestionText.GetHashCode(); 
            return hash; 
        }
 }

public class QuestionTrueFalse : Question
    {
        public bool CorrectAnswer
        {
            get;
            set;
        }

        public override bool Equals(object obj)
        {
            return base.Equals(q);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode(); 
        }
    } 
  

Производный класс не влияет на то, равен ли один элемент другому, я все еще хочу, чтобы это основывалось просто на свойстве questionText.

Нужно ли мне переопределять Equals и GetHashCode для ссылки на базовую реализацию, как я сделал здесь, или это поведение по умолчанию?

Комментарии:

1. Почему бы вам просто не написать public override int GetHashCode() { return 91 this.QuestionText.GetHashCode(); } ?

Ответ №1:

Поведение базового класса наследуется наследующими классами. Вам не нужно явно переопределять Equals и GetHashCode , если вы не хотите изменить их поведение.

Комментарии:

1. Идеальный ответ. Я просто хотел добавить, что переопределение метода для вызова версии базового типа вообще не влияет на поведение программы (если вы не используете отражение).

Ответ №2:

  1. Вы, вероятно, этого не хотите. Почему вы хотели бы иметь отдельные, но равные экземпляры объекта question?

  2. Вам, по крайней мере, придется добавить operator== и operator!= , чтобы избежать неприятных сюрпризов.

  3. Но нет, вам не нужно переопределять в QuestionTrueFalse для вызова базовой реализации. Это предусмотрено.

Стандартный пример (не могу придумать более подходящий для ПК):

Вопрос 1: «Ты все еще бьешь свою жену?» { true, false }
Вопрос 2: «Ты все еще бьешь свою жену?» { true, false, N / A }

Действительно ли они одинаковы?

Ответ №3:

Создать класс, производный от класса, который заботится о Equals и GetHashCode, не так просто. Многие соображения опущены, если просто позволить базовому классу выполнять эту работу.

Вы можете обратиться к этой статье для более глубокого анализа того, как меняется назначение методов Equals и GetHashCode после создания класса: Как переопределить методы Equals и GetHashCode в базовом и производных классах