3

I have a class:

public abstract class AbstractDictionaryObject
    {
        public virtual int LangId { get; set; }

        public override bool Equals(object obj)
        {
            if (obj == null || obj.GetType() != GetType())
            {
                return false;
            }

            AbstractDictionaryObject other = (AbstractDictionaryObject)obj;
            if (other.LangId != LangId)
            {
                return false;
            }

            return true;
        }

        public override int GetHashCode()
        {
            int hashCode = 0;               
            hashCode = 19 * hashCode + LangId.GetHashCode();
            return hashCode;
        }

And I have derived classes:

public class Derived1:AbstractDictionaryObject
{...}

public class Derived2:AbstractDictionaryObject
{...}

In the AbstractDictionaryObject is only one common field: LangId.
I think this is not enough to overload methods (properly).
How can I identify objects?

user348173
  • 8,818
  • 18
  • 66
  • 102

1 Answers1

7

For one thing you can simplify both your methods:

 public override bool Equals(object obj)
 {
     if (obj == null || obj.GetType() != GetType())
     {
         return false;
     }

     AbstractDictionaryObject other = (AbstractDictionaryObject)obj;
     return other.LangId == LangId;
 }

 public override int GetHashCode()
 {
     return LangId;
 }

But at that point it should be fine. If the two derived classes have other fields, they should override GetHashCode and Equals themselves, first calling base.Equals or base.GetHashCode and then applying their own logic.

Two instances of Derived1 with the same LangId will be equivalent as far as AbstractDictionaryObject is concerned, and so will two instances of Derived2 - but they will be different from each other as they have different types.

If you wanted to give them different hash codes you could change GetHashCode() to:

 public override int GetHashCode()
 {
     int hash = 17;
     hash = hash * 31 + GetType().GetHashCode();
     hash = hash * 31 + LangId;
     return hash;
 }

However, hash codes for different objects don't have to be different... it just helps in performance. You may want to do this if you know you will have instances of different types with the same LangId, but otherwise I wouldn't bother.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • "Two instances of Derived1 with the same LangId will be equivalent" - this is bad for my situation. Can I introduce the GUID field? Because i don't want to override in derived classes. – user348173 Aug 10 '11 at 05:48
  • @user348173: If you want every instance to be unequal to every other instance, then why are you overriding Equals and GetHashCode at all? It's not clear what you're trying to achieve. When should two distinct objects be considered equal? – Jon Skeet Aug 10 '11 at 05:57
  • they are equal if langId is equal and other field which exist in Derived1 is equal. – user348173 Aug 10 '11 at 06:33
  • for example, I have two instances of Derived1: Class1 and Class2. The field LangId is equal, but other field (for example - Name) is different. So Class1 and Class2 should be not equal. But I don't want to override Equals and GetHashCode in Derived1. – user348173 Aug 10 '11 at 06:38
  • @user348173: But you *should* override Equals and GetHashCode in Derived1. You could *potentially* use reflection to examine the fields, but that would be slow and very brittle - you might want to introduce a field which *isn't* part of the equality contract in Derived1. Fundamentally the base class can't predict which aspects of the class are part of its idea of equality - so you need to provide that behaviour within each derived class. **Why** don't you want to override GetHashCode/Equals within Derived1? – Jon Skeet Aug 10 '11 at 06:39
  • @user348173 Then you would have to override `Equals` and `GetHashCode` in Derived1. A base does not know about fields you add to derived classes. – Alexey Ivanov Aug 10 '11 at 06:40
  • @Jon Skeet: Initially, I did not have class AbstractDictionaryObject. And each class implements the Equals and GetHashCode. I wanted to do it only once, in the base class. Therefore, I have created class AbstractDictionaryObject. – user348173 Aug 10 '11 at 06:46
  • @user348173: But it sounds like each class has its own fields and thus its own idea of equality - so you can't put that logic in one place. You could potentially write helper methods to pass the relevant information up to the base class, but fundamentally you've got to communicate the idea of "this set of information makes up the equality key" *somehow* from the derived class to the base class. – Jon Skeet Aug 10 '11 at 07:21