using System.Collections.Generic;
public static void Main()
var testDict = new Dictionary<UnorderedPair<int>, string>();
testDict.Add(new UnorderedPair<int>(1, 2), "Hello World!");
Console.WriteLine(testDict[new UnorderedPair<int>(2, 1)]);
var testDict2 = new Dictionary<UnorderedPair<int, double>, string>();
testDict2.Add(new UnorderedPair<int, double>(1,2.5), "Still Hello World!");
Console.WriteLine(testDict2[new UnorderedPair<double,int>(2.5,1)]);
var testDict3 = new Dictionary<UnorderedPair<float, float>, string>();
testDict3.Add(new UnorderedPair<float,float>()
}, "Aaaand Still Hello World!");
Console.WriteLine(testDict3[new UnorderedPair<float,float>()
public class UnorderedPair<T> : IEquatable<UnorderedPair<T>>
public UnorderedPair(T x, T y)
public bool Equals(UnorderedPair<T> other)
if (ReferenceEquals(null, other))
if (ReferenceEquals(this, other))
return X.Equals(other.X) && Y.Equals(other.Y) || X.Equals(other.Y) && Y.Equals(other.X);
public override bool Equals(object obj)
if (ReferenceEquals(null, obj))
if (ReferenceEquals(this, obj))
if (obj.GetType() != GetType())
return Equals((UnorderedPair<T>)obj);
public override int GetHashCode()
var hashX = X == null ? 0 : X.GetHashCode();
var hashY = Y == null ? 0 : Y.GetHashCode();
return HashCode.Combine(Math.Min(hashX,hashY), Math.Max(hashX,hashY));
public static bool operator ==(UnorderedPair<T> left, UnorderedPair<T> right)
return Equals(left, right);
public static bool operator !=(UnorderedPair<T> left, UnorderedPair<T> right)
return !Equals(left, right);
public class UnorderedPair<TX, TY> : IEquatable<UnorderedPair<TX, TY>>
public UnorderedPair(TX x, TY y)
public UnorderedPair(TY y, TX x)
public override int GetHashCode()
var hashX = X == null ? 0 : X.GetHashCode();
var hashY = Y == null ? 0 : Y.GetHashCode();
var combine = HashCode.Combine(Math.Min(hashX, hashY), Math.Max(hashX, hashY));
public bool Equals(UnorderedPair<TX, TY> other)
if (ReferenceEquals(null, other))
if (ReferenceEquals(this, other))
if (typeof(TX) != typeof(TY))
return EqualityComparer<TX>.Default.Equals(X, other.X) && EqualityComparer<TY>.Default.Equals(Y, other.Y);
return EqualityComparer<TX>.Default.Equals(X, other.X) && EqualityComparer<TY>.Default.Equals(Y, other.Y)
|| X.Equals(other.Y) && Y.Equals(other.X);
public override bool Equals(object obj)
if (ReferenceEquals(null, obj))
if (ReferenceEquals(this, obj))
UnorderedPair<TX, TY> other => Equals(other),
UnorderedPair<TY, TX> otherSwapped => Equals(otherSwapped),
public static bool operator ==(UnorderedPair<TX, TY> left, UnorderedPair<TX, TY> right)
return Equals(left, right);
public static bool operator !=(UnorderedPair<TX, TY> left, UnorderedPair<TX, TY> right)
return !Equals(left, right);
public static implicit operator UnorderedPair<TX, TY>(UnorderedPair<TY, TX> pair)
return new UnorderedPair<TX, TY>(pair.Y, pair.X);