开发者

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 implement IEqualityComparer<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 that L and R 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. just My_tuple) to allow type inference to work, e.g. My_tuple.Create(1, "hello") to create a My_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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜