In the internal source there is such a constructor public HashSetEqualityComparer(IEqualityComparer
but it\'s internal so I can\'t use it.<
I agree @InBetween, using SetEquals
is the best way. Even if add the constructor still can not achieve what you want.
please see this code: http://referencesource.microsoft.com/#System.Core/System/Collections/Generic/HashSet.cs,1360
Here is I try to do:
class HashSetEqualityComparerWrapper : IEqualityComparer>
{
static private Type HashSetEqualityComparerType = HashSet.CreateSetComparer().GetType();
private IEqualityComparer> _comparer;
public HashSetEqualityComparerWrapper()
{
_comparer = HashSet.CreateSetComparer();
}
public HashSetEqualityComparerWrapper(IEqualityComparer comparer)
{
_comparer = HashSet.CreateSetComparer();
if (comparer != null)
{
FieldInfo m_comparer_field = HashSetEqualityComparerType.GetField("m_comparer", BindingFlags.NonPublic | BindingFlags.Instance);
m_comparer_field.SetValue(_comparer, comparer);
}
}
public bool Equals(HashSet x, HashSet y)
{
return _comparer.Equals(x, y);
}
public int GetHashCode(HashSet obj)
{
return _comparer.GetHashCode(obj);
}
}
I took 5 mins to implement another version form HashSetEqualityComparer
source code. And rewrite the bool Equals(HashSet
method. It is not complex. All code just copy and paste from source, I just revise a bit.
class CustomHashSetEqualityComparer : IEqualityComparer>
{
private IEqualityComparer m_comparer;
public CustomHashSetEqualityComparer()
{
m_comparer = EqualityComparer.Default;
}
public CustomHashSetEqualityComparer(IEqualityComparer comparer)
{
if (comparer == null)
{
m_comparer = EqualityComparer.Default;
}
else
{
m_comparer = comparer;
}
}
// using m_comparer to keep equals properties in tact; don't want to choose one of the comparers
public bool Equals(HashSet x, HashSet y)
{
// http://referencesource.microsoft.com/#System.Core/System/Collections/Generic/HashSet.cs,1360
// handle null cases first
if (x == null)
{
return (y == null);
}
else if (y == null)
{
// set1 != null
return false;
}
// all comparers are the same; this is faster
if (AreEqualityComparersEqual(x, y))
{
if (x.Count != y.Count)
{
return false;
}
}
// n^2 search because items are hashed according to their respective ECs
foreach (T set2Item in y)
{
bool found = false;
foreach (T set1Item in x)
{
if (m_comparer.Equals(set2Item, set1Item))
{
found = true;
break;
}
}
if (!found)
{
return false;
}
}
return true;
}
public int GetHashCode(HashSet obj)
{
int hashCode = 0;
if (obj != null)
{
foreach (T t in obj)
{
hashCode = hashCode ^ (m_comparer.GetHashCode(t) & 0x7FFFFFFF);
}
} // else returns hashcode of 0 for null hashsets
return hashCode;
}
// Equals method for the comparer itself.
public override bool Equals(Object obj)
{
CustomHashSetEqualityComparer comparer = obj as CustomHashSetEqualityComparer;
if (comparer == null)
{
return false;
}
return (this.m_comparer == comparer.m_comparer);
}
public override int GetHashCode()
{
return m_comparer.GetHashCode();
}
static private bool AreEqualityComparersEqual(HashSet set1, HashSet set2)
{
return set1.Comparer.Equals(set2.Comparer);
}
}