Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 603
Kalevi Avatar asked Mar 12 '16 19:03

Kalevi


2 Answers

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.

like image 130
Cory Nelson Avatar answered Sep 28 '22 04:09

Cory Nelson


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;
        }
    }
like image 43
tmitchel2 Avatar answered Sep 28 '22 03:09

tmitchel2