Currently I have this (edited after reading advice):
struct Pair<T, K> : IEqualityComparer<Pair<T, K>>
{
readonly private T _first;
readonly private K _second;
public Pair(T first, K second)
{
_first = first;
_second = second;
}
public T First { get { return _first; } }
public K Second { get { return _second; } }
#region IEqualityComparer<Pair<T,K>> Members
public bool Equals(Pair<T, K> x, Pair<T, K> y)
{
return x.GetHashCode(x) == y.GetHashCode(y);
}
public int GetHashCode(Pair<T, K> obj)
{
int hashCode = obj.First == null ? 0 : obj._first.GetHashCode();
hashCode ^= obj.Second == null ? 0 : obj._second.GetHashCode();
return hashCode;
}
#endregion
public override int GetHashCode()
{
return this.GetHashCode(this);
}
public override bool Equals(object obj)
{
return (obj != null) &&
(obj is Pair<T, K>) &&
this.Equals(this, (Pair<T, K>) obj);
}
}
The problem is that First and Second may not be reference types (VS actually warns me about this), but the code still compiles. Should I cast them (First and Second) to objects before I compare them, or is there a better way to do this?
Edit: Note that I want this struct to support value and reference types (in other words, constraining by class is not a valid solution)
Edit 2: As to what I'm trying to achieve, I want this to work in a Dictionary. Secondly, SRP isn't important to me right now because that isn't really the essence of this problem - it can always be refactored later. Thirdly, comparing to default(T) will not work in lieu of comparing to null - try it.
Your IEqualityComparer implementation should be a different class (and definately not a struct as you want to reuse the reference).
Also, your hashcode should never be cached, as the default GetHashcode implementation for a struct (which you do not override) will take that member into account.
It looks like you need IEquatable instead:
internal struct Pair<T, K> : IEquatable<Pair<T, K>>
{
private readonly T _first;
private readonly K _second;
public Pair(T first, K second)
{
_first = first;
_second = second;
}
public T First
{
get { return _first; }
}
public K Second
{
get { return _second; }
}
public bool Equals(Pair<T, K> obj)
{
return Equals(obj._first, _first) && Equals(obj._second, _second);
}
public override bool Equals(object obj)
{
return obj is Pair<T, K> && Equals((Pair<T, K>) obj);
}
public override int GetHashCode()
{
unchecked
{
return (_first != null ? _first.GetHashCode() * 397 : 0) ^ (_second != null ? _second.GetHashCode() : 0);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With