using System.Collections.Generic;
public static void Main()
var std = new HashSet<int[]>(new[] { new[] { 1, 2 }, new[] { 2, 2}});
std.ExceptWith(new[] { new[] { 2, 2}});
var custom = new HashSet<int[]>(new[] { new[] { 1, 2 }, new[] { 2, 2 } }, new ROCollectionComparer<int>());
custom.ExceptWith(new[] { new[] { 2, 2 }});
custom.ExceptWith(new[] { new int[] { }});
class ROCollectionComparer<T> : IEqualityComparer<IReadOnlyCollection<T>>
private readonly IEqualityComparer<T> elementComparer;
public ROCollectionComparer() : this(EqualityComparer<T>.Default) {}
public ROCollectionComparer(IEqualityComparer<T> elementComparer) {
this.elementComparer = elementComparer;
public bool Equals(IReadOnlyCollection<T> x, IReadOnlyCollection<T> y)
if(x== null && y == null) return true;
if(x == null || y == null) return false;
if(object.ReferenceEquals(x, y)) return true;
return x.Count == y.Count &&
x.SequenceEqual(y, elementComparer);
public int GetHashCode(IReadOnlyCollection<T> obj)
return Tuple.Create(obj.Count, obj.Count == 0 ? 0 : elementComparer.GetHashCode(obj.First())).GetHashCode();