Implement IEquatable<T> when T could be IEnumerable<T>

c#, implementation, structural-equality

Solution

You could have your `MyObject<T>` take an equality comparer for your type `T` and use that:

class MyObject<T> : IEquatable<MyObject<T>>
{
    private readonly IEqualityComparer<T> comparer;
    public MyObject(string otherProp, T value, IEqualityComparer<T> comparer)
    {
        this.comparer = comparer;
    }
    public MyObject(string otherProp, T value)
        : this(otherProp, value, EqualityComparer<T>.Default)
    {
    }

    public bool Equals(MyObject<T> other)
    {
        return OtherProp.Equals(other.OtherProp) && comparer.Equals(this.Value, other.Value);
    }
}

Then for `IEnumerable<T>` you can use a comparer which compares the sequences instead of the references. You might want to make use of factory methods to create your objects to ensure the same comparer type is used for the same `T` to ensure equality remains symmetric.

Problem

I've read various questions similar to mine but none of them seem address my issue. I've a type like this: ``` class MyObject<T> : IEquatable<MyObject<T>> { // no generic constraints private readonly string otherProp; private readonly T value; public MyObject(string otherProp, T value) { this.otherProp = otherProp; this.value = value; } public string OtherProp { get { return this.otherProp; } } public T Value { get { return this.value; } } // ... public bool Equals(MyObject<T> other) { if (other == null) { return false; } return this.OtherProp.Equals(other.OtherProp) && this.Value.Equals(other.Value); } } ``` When `T` is a scalar as `MyObject<int>` equality works correctly, but when I defined something like `MyObject<IEnumerable<int>>` equality fails. The reason is that when T is `IEnumerable<T>` I should call `this.Value.SequenceEqual(other.Value)`. Handling this difference bloats `Equals(MyObject<T>)` with too LOC of type check and reflection (for me, leading to a violation of SOLID/SRP). I was not able to found this specific case in MSDN guidelines, so if anyone already faced this problem; it would be great if this knowledge can be shared. Edit: Alternative To K.I.S.S., I'm wondering to doing something similar: ``` class MyObject<T> : IEquatable<MyObject<T>> { private readonly IEnumerable<T> value; // remainder omitted } ``` In this way the implementation of `Equal` will be a lot simple. And when I need just one value I've a collection of 1 item. Obviously T will not be an enumerable (but the data structure is private so there's no problem).

Original source