I am writing this question in the context of a DDD application. I found this code online on a number of blogs etc e.g. here and here.
public abstract class ValueObject<T>
where T : ValueObject<T>
{
protected abstract IEnumerable<object> GetEqualityComponents();
public override bool Equals(object obj)
{
var valueObject = obj as T;
if (ReferenceEquals(valueObject, null))
return false;
return EqualsCore(valueObject);
}
private bool EqualsCore(ValueObject<T> other)
{
return GetEqualityComponents().SequenceEqual(other.GetEqualityComponents());
}
public override int GetHashCode()
{
return GetEqualityComponents()
.Aggregate(1, (current, obj) => current * 23 + (obj?.GetHashCode() ?? 0));
}
public static bool operator ==(ValueObject<T> a, ValueObject<T> b)
{
if (ReferenceEquals(a, null) && ReferenceEquals(b, null))
return true;
if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
return false;
return a.Equals(b);
}
public static bool operator !=(ValueObject<T> a, ValueObject<T> b)
{
return !(a == b);
}
}
}
Every Value Object in my application inherits from it. It means the methods like: Equals
and GetHashCode
are dealt with implicitly. The main problem I see arises if I want to add a collection e.g. array as a member of a Value Object - in this scenario the generic value object .Equals
will not behave as expected as it cannot deal with collections.
Therefore:
- Can this class be tweaked to deal with collections?
- Are there any other downfalls with this approach?
- Is it advisable not to use a generic value class when developing a DDD application?
EqualsCore
to beprotected virtual
to allow derived classes with generic collection arguments to be able to override and determine equality themselves. \$\endgroup\$GetEqualityComponents
but that appears to be premature optimization to me. \$\endgroup\$GetEqualityComponents
implementation by using the collections enumeration for the components. \$\endgroup\$