Using a Generic Value Object in a DDD application 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&lt;T&gt; 
         where T : ValueObject&lt;T&gt; 
     { 
        protected abstract IEnumerable&lt;object&gt; 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&lt;T&gt; other) 
         { 
             return GetEqualityComponents().SequenceEqual(other.GetEqualityComponents()); 
         }  

         public override int GetHashCode() 
         { 
             return GetEqualityComponents() 
                 .Aggregate(1, (current, obj) =&gt; current * 23 + (obj?.GetHashCode() ?? 0)); 
         } 


         public static bool operator ==(ValueObject&lt;T&gt; a, ValueObject&lt;T&gt; b) 
        { 
             if (ReferenceEquals(a, null) &amp;&amp; ReferenceEquals(b, null)) 
                 return true; 


             if (ReferenceEquals(a, null) || ReferenceEquals(b, null)) 
                 return false; 


             return a.Equals(b); 
         } 


         public static bool operator !=(ValueObject&lt;T&gt; a, ValueObject&lt;T&gt; 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?
Using the code in your example along with the following article for reference

Representing a collection as a Value Object

Lets start with refactoring the City value object to use the improved ValueObject

public sealed class City : ValueObject&lt;City&gt; {

    public string Name { get; }
    public bool IsEnabled { get; }

    public City(string name, bool isEnabled) {
        Name = name;
        IsEnabled = isEnabled;
    } 

    protected override IEnumerable&lt;object&gt; GetEqualityComponents() {
        yield return Name; 
        yield return IsEnabled;
    }
}


Note how GetEqualityComponents was implemented. Reflection could also have been used to enumerate the properties as needed

return this.GetType().GetProperties().Select(propInfo =&gt; propInfo.GetValue(this, null);


There is room for improvement above and I will leave that as an exercise.

For collections, the GetEqualityComponents allows for a simplified approach of returning the items used to check equality.

public class CityList : ValueObject&lt;CityList&gt;, IEnumerable&lt;City&gt; {

    private List&lt;City&gt; _cities { get; }

    public CityList(IEnumerable&lt;City&gt; cities) {
        _cities = cities.ToList();
    }

    protected override IEnumerable&lt;object&gt; GetEqualityComponents() {
        return this.OrderBy(c =&gt; c.Name);
    }

    public IEnumerator&lt;City&gt; GetEnumerator() {
        return _cities.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator() {
        return GetEnumerator();
    }
}


Note that since the collection already implements IEnumerable one simple needs to return the desired enumeration that will be used to calculate equality.

GetEqualityComponents() proves to be a very convenient approach and really does improve and simplify how the ValueObject can be implemented. I initially though it to be a premature optimization attempt but having taken some time to review its potential I have changed my initial view of its function.

UPDATE from comments about the potential of using reflection.:


  The use of reflection automates and simplifies a repetitive task with
  a minor performance trade off. Caching the property/field info could
  help a little but I personally have had no issues with it performance
  wise. Also using reflection grabs all while using the yield like in
  the example you get to be selective of which ones to use for equality.
  You can make an extension method to get the best of both worlds and
  have options.


public static class ValueObjectExtensions {
    /// &lt;summary&gt;
    /// Uses reflection to extract all public properties from the target value object
    /// &lt;/summary&gt;
    public static IEnumerable&lt;object&gt; GetComponents&lt;T&gt;(this ValueObject&lt;T&gt; target)
        where T : ValueObject&lt;T&gt; {
        return target.GetType().GetProperties().Select(propInfo =&gt; propInfo.GetValue(target, null));
    }
}


and used like

protected override IEnumerable&lt;object&gt; GetEqualityComponents() {
   return this.GetComponents(); //&lt;-- calling extension method
}