Equality comparison for a surname value object class

Posted on

Problem

I asked this question yesterday: Entity and Value Object are not part of the Ubiqtious language. Should this stop me from using them?.

I originally decided to introduce a ValueObject class as described here: Generic Value Object Equality, which contained equality methods for all value objects i.e. all Value Objects inherited from ValueObject the value object class. However, this approach was criticised.

Please see the code below:

public sealed class Surname : IEquatable<Surname>
{
    private readonly string _value;
    public Surname(string surname)
    {
        if (surname.Length==0)
            throw new ArgumentException("Invalid value.", "Surname");
        this._value = surname;
    }

    public string Value
    {
        get { return _value; }
    }

    public static bool operator ==(Surname surname1, Surname surname2)
    {
        if (!ReferenceEquals(surname1, null) &&
            ReferenceEquals(surname2, null))
        {
            return false;
        }
        if (ReferenceEquals(surname1, null) &&
             !ReferenceEquals(surname2, null))
        {
            return false;
        }
        return surname1.Equals(surname2);
    }

    public static bool operator !=(Surname surname1, Surname surname2)
    {
        return !(surname1== surname2);
    }

    public bool Equals(Surname other)
    {
        if (other != null)
        {
            return _value == other._value;
        }
        return base.Equals(other);
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as Surname);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 17;
            hash = hash * 23 + _value.GetHashCode();
            return hash;
        }
    }
}

It is a DDD Value Object for a Surname.

I have added some methods for equality and:

  1. I would like some feedback on the quality of them.

  2. This question (point one) links to a presentation by Eric Evans where he appears to advise against introducing equality for Entities. Is it advisable to always compare entities by reference these days?

Solution

I don’t see any advantage that this class provides over a simple string. I expect a Surname to be at least case-insensitive but this class’ equality is exactly the same as if it was a string.

I also don’t understand why you change the hashcode of the string? You could just return the one that _value returns… but agian, this would be the same as an the one of an ordinary string.

Take a look a the StringComparer.OrdinalIgnoreCase because this is what you actually need… I guess. It would make sense.

As far as a Surname is concerned I also expect it to yield true when comparing "John" with " John ". So you might want to Trim the value.


This kind of case-insensitive trimmed string is such a common use case that I have special class for that. It saves a lots of headaches when working this kind of data.

Leave a Reply

Your email address will not be published. Required fields are marked *