元组实现

时间:2010-08-16 10:10:31

标签: c# .net

我已经实现了某些版本的元组类,并且真的想从中学到更多。

请您指点我在实施时遗漏的一些问题。

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)
        {
            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

    }

感谢。

2 个答案:

答案 0 :(得分:13)

一些事情:

  • 类型名称不符合.NET约定
  • 各种参数名称不符合.NET约定
  • 您不应该从EqualityComparer<T>派生 - 您应该实施IEqualityComparer<T>
  • GetHashCode()的实施不理想;这意味着对于具有相同类型的左右(例如My_tuple<int, int>)且值相等的任何元组,您将获得相同的哈希码0.即(1,1)具有相同的哈希码as(2,2)等。我更喜欢“添加和乘法”实现 - 在这种情况下,您可以返回(比方说)17 * hash1 + 31 * hash2。仍然会有碰撞,但希望不会那么多。
  • Equals(L, R)的实施假设LR非空
  • 您的Create方法是通用的,尝试重新声明T1和T2类型参数。我很惊讶甚至编译,虽然这是我以前没有尝试过的东西。考虑在非泛型类(例如,仅My_tuple)中创建静态泛型方法,以允许类型推断工作,例如My_tuple.Create(1, "hello")创建My_tuple<int, string>
  • 我个人会使用私有只读字段和简单属性getter,而不是自动属性。声明并不是很明显,你永远不会改变属性的值 - 你必须阅读所有的代码。

答案 1 :(得分:2)

除了Jon提到的观点之外,目前看起来还不错,请记住,您总是可以使用Reflector查看真实的Tuple实现,以获得更多洞察力。

你实现了所有运营商和结构平等,很好。我注意到你的工厂方法:

    public static My_tuple<T1, T2> Create<T1, T2>(T1 first, T2 second)
    {
        return new My_tuple<T1, T2>(first, second);
    }

应该放在一个单独的静态类(例如Tuple)上,因此元组的使用者可以利用C#编译器类型推断来创建元组,而无需显式指定泛型类型参数。