Tuple Implementation
I have implemented some version of tuple class , and really want to learn more from it .
Can you please point me on some points that I am missing here with my implementation.
class My_tuple<T1, T2> : EqualityComparer<My_tuple<T1, T2>>
{
#region Virables
public T1 First { get; private set; }
public T2 Second { get; private set; }
#endregion
#region Constractors
public My_tuple(T1 first, T2 second)
{
First = first;
Second = second;
}
#endregion
#region Equals && GetHashCode
public override bool Equals(My_tuple<T1, T2> L, My_tuple<T1, T2> R)
{
return EqualityComparer<T1>.Default.Equals(L.First, R.First) && EqualityComparer<T2>.Default.Equals(L.Second , R.Second);
}
public override bool Equals(object obj)
{
return obj is My_tuple<T1, T2> && Equals(this, (My_tuple<T1, T2>)obj);
}
public override int GetHashCode(My_tuple<T1, T2> M)
{
return M.First.GetHashCode() ^ M.Second.GetHashCode();
}
#endregion
#region operators
public static bool operator ==(My_tuple<T1, T2> left, My_tuple<T1, T2> right)
{
return left.Equals(right);
}
public static bool operator !=(My_tuple<T1, T2> left, My_tuple<T1, T2> right)
{
开发者_StackOverflow return !(left == right);
}
public static My_tuple<T1, T2> Create<T1, T2>(T1 first, T2 second)
{
return new My_tuple<T1, T2>(first, second);
}
#endregion
}
Thanks.
A few things:
- The type name doesn't comply with .NET conventions
- Various parameter names don't comply with .NET conventions
- You shouldn't derive from
EqualityComparer<T>
- you should implementIEqualityComparer<T>
. - Your implementation of
GetHashCode()
is non-ideal; it means that for any tuple with the same type of left and right (e.g.My_tuple<int, int>
) where the values are equal, you'll get the same hash code of 0. i.e. (1, 1) has the same hash code as (2, 2) etc. I prefer an "add and multiply" implementation - in this case you could return (say)17 * hash1
+31 * hash2
. There will still be collisions, but hopefully not as many. - Your implementation of
Equals(L, R)
assumes thatL
andR
are non-null - Your
Create
method is generic, attempting to redeclare the T1 and T2 type parameters. I'm surprised that even compiles, although it's something I haven't tried before. Consider creating a static generic method in a non-generic class (e.g. justMy_tuple
) to allow type inference to work, e.g.My_tuple.Create(1, "hello")
to create aMy_tuple<int, string>
- I would personally use private readonly fields and simple property getters, rather than automatic properties. It's not immediately obvious from the declaration that you'll never change the values of the properties - you have to read all of the code.
Looks good so far besides the points Jon mentioned, remember you can always look at the real Tuple implementation using Reflector to gain more insight.
You implemented all operators and structural equality, good. I noticed that your factory method:
public static My_tuple<T1, T2> Create<T1, T2>(T1 first, T2 second)
{
return new My_tuple<T1, T2>(first, second);
}
should be put on a separate, static class (e.g. Tuple) so consumers of the tuple can leverage the C# compilers type inference to create tuples without explicitly specifying the generic type arguments.
精彩评论