0

I'm not really sure, why grouping by IEnumerable<string> does not work. I provide custom IEqualityComparer, of course.

public class StringCollectionEqualityComparer : EqualityComparer<IEnumerable<string>>
{
    public override bool Equals(IEnumerable<string> x, IEnumerable<string> y)
    {
        if (Object.Equals(x, y) == true)
            return true;
        if (x == null) return y == null;
        if (y == null) return x == null;

        return x.SequenceEqual(y, StringComparer.OrdinalIgnoreCase);
    }

    public override int GetHashCode(IEnumerable<string> obj)
    {
        return obj.OrderBy(value => value, StringComparer.OrdinalIgnoreCase).Aggregate(0, (hashCode, value) => value == null ? hashCode :  hashCode ^ value.GetHashCode() + 33);
    }
}

class A
{
    public IEnumerable<string> StringCollection { get; set; }
}

IEnumerable<A> collection = // collection of A

var grouping = collection.GroupBy(obj => a.StringCollection, StringCollectionEqualityComparer.Default).ToList();

(ToList() is to force evaluation, I have breakpoints in StringCollectionEqualityComparer, but unfortunately, they're not invoked, as expected)

When I group collection in this dumb way, it actually works.

var grouping = collection.GroupBy(obj => String.Join("|", obj.StringCollection));

Unfortunately, obviously it is not something I want to use.

By not working, I mean the results are not the ones I expect (using dumb way, the results are correct).

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
mnn
  • 1,952
  • 4
  • 28
  • 51

1 Answers1

6

StringCollectionEqualityComparer.Default is a valid alternative way to access EqualityComparer<IEnumerable<string>>.Default, since the latter is a base class of the former. You need to create an instance of StringCollectionEqualityComparer, simply using new StringCollectionEqualityComparer(), instead.

  • Thanks! Looks like I have some extra learning to do regarding generics and this "issue". Now I know, why my custom `EqualityComparer`s have been failing :) – mnn Apr 17 '13 at 20:44
  • 2
    Glad it helped, but it's not actually related to generics. Static members of base classes are always accessible through derived types, which is why seemingly nonsensible code such as `if (int.Equals(1.2, "wtf")) { ... }` is valid: that actually calls `object.Equals(1.2, "wtf")`. –  Apr 17 '13 at 20:49
  • Thanks for clarification. I believed that I had already known such low level parts of .NET Framework. Next time, I won't assume anything. – mnn Apr 17 '13 at 21:06