Kalevi
Kalevi

Reputation: 591

System.Collections.Immutable types: why no .Equals

var a = ImmutableList<int>.Empty.Add(1).Add(2).Add(3);
var b = ImmutableList<int>.Empty.Add(1).Add(2).Add(3);

Console.WriteLine(a.Equals(b)); // False

In the code above the a.Equals(b) calls Object.Equals, because ImmutableList<T> doens't override Equals(object), and as ImmutableList<T> is a reference type Object.Equals does (the useless) reference comparison.

Question: Why doesn't ImmutableList<T> override .Equals? It would be straightforward and expected to have it compare each contained object with .Equals and return the result based on those comparisons. It would even be consistent to test rest of the framework (see class String )

note: the above code is tested with System.Collections.Immutable.1.1.38-beta-23516

Upvotes: 9

Views: 2405

Answers (3)

tmitchel2
tmitchel2

Reputation: 55

You 'could' create a wrapper class and override the Equality and HashCode methods... This could be helpful for c# records so that you don't have to keep overriding the auto generated methods.

    public sealed class ImmutableListSequence<T>
    {
        public ImmutableListSequence(ImmutableList<T> items)
        {
            Items = items;
        }

        public ImmutableList<T> Items { get; }

        public override int GetHashCode()
        {
            unchecked
            {
                return Items.Aggregate(0, (agg, curr) => (agg * 397) ^ (curr != null ? curr.GetHashCode() : 0));
            }
        }

        public override bool Equals(object? obj)
        {
            if (obj is ImmutableListSequence<T> second)
            {
                return Items.SequenceEqual(second.Items);
            }

            return false;
        }
    }

Upvotes: 2

B.K.
B.K.

Reputation: 10152

None of the collections do. They all inherit Object.Equals(Object) and don't override it. Use Enumerable.SequenceEqual method to compare elements of two collections.

Upvotes: 0

Cory Nelson
Cory Nelson

Reputation: 29981

You want to do is test the contents of the collections for equality. No .NET collections override Equals to do this. Instead, use SequenceEqual:

Console.WriteLine(a.SequenceEqual(b));

As to why -- that's a matter of opinion, I suppose. Most reference oriented platforms do their best to not confuse reference equality with content equality.

String is actually very special case and though it does implement IEnumerable, isn't typically treated as a proper container in the sense that List/etc. are.

Upvotes: 4

Related Questions