zoukankan      html  css  js  c++  java
  • NET4.0中非常好用的一个东西Tuple

     最近发现了.NET4.0中一个非常好用的东西Tuple,自从知道了它之后,发现我的代码里面到处都是它的身影。那么Tuple究竟是何物呢?

           在知道Tuple之前,我经常碰到要使用一些记录的集合,如果每条记录只有一个元素,一般都是用List来存储,如果每条记录,我想记录两个属性,我一般用Dictionary<int,int>来存储,但是如果每个记录要记录三个属性,甚至四个属性的时候,那么我们只能定义一个数据结构或者实体类来进行存储,然后再把这个实体装到List中去。但是大多数时候,这么一个List的列表只是临时用一下,所以如果再去定义一个数据结构,就觉得有点不划算,那该怎么办呢?这时Tuple就该上场了。

          Tuple是元组的意思,它有八种形式(注意这里并不是说Tuple类有八种构造函数,而是八个不同的类,每种形式都是一个单独的类),它里面可以装任意多的元素,它的形式如下:

    image

          如果你的元素个数小于8,那么你可以直接调用相应的构造函数,如果你的元素个数大于8,那也不要紧,我们可以看到最后一个构造函数的最后一个参数是TRest,TRest也是Tuple类型的,这就说明,你可以在Tuple里面加入任意多的元素。

          下面以Tuple<T1>为例,来看看它里面具体的内容,它的内部代码如下:

    [Serializable]
        
    public class Tuple<T1> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple
        
    {
        
        private readonly T1 m_Item1;
        
        public T1 Item1
        
        {
        
            get
        
            {
        
                return this.m_Item1;
        
            }
        
        }
        
        int ITuple.Size
        
        {
        
            get
        
            {
        
                return 1;
        
            }
        
        }
        
        public Tuple(T1 item1)
        
        {
        
            this.m_Item1 = item1;
        
        }
        
        public override bool Equals(object obj)
        
        {
        
            return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default);
        
        }
        
        bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
        
        {
        
            if (other == null)
        
            {
        
                return false;
        
            }
        
            Tuple<T1> tuple = other as Tuple<T1>;
        
            return tuple != null && comparer.Equals(this.m_Item1, tuple.m_Item1);
        
        }
        
        int IComparable.CompareTo(object obj)
        
        {
        
            return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
        
        }
        
        int IStructuralComparable.CompareTo(object other, IComparer comparer)
        
        {
        
            if (other == null)
        
            {
        
                return 1;
        
            }
        
            Tuple<T1> tuple = other as Tuple<T1>;
        
            if (tuple == null)
        
            {
        
                throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", new object[]
        
                {
        
                    base.GetType().ToString()
        
                }), "other");
        
            }
        
            return comparer.Compare(this.m_Item1, tuple.m_Item1);
        
        }
        
        public override int GetHashCode()
        
        {
        
            return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
        
        }
        
        int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
        
        {
        
            return comparer.GetHashCode(this.m_Item1);
        
        }
        
        int ITuple.GetHashCode(IEqualityComparer comparer)
        
        {
        
            return ((IStructuralEquatable)this).GetHashCode(comparer);
        
        }
        
        public override string ToString()
        
        {
        
            StringBuilder stringBuilder = new StringBuilder();
        
            stringBuilder.Append("(");
        
            return ((ITuple)this).ToString(stringBuilder);
        
        }
        
        string ITuple.ToString(StringBuilder sb)
        
        {
        
            sb.Append(this.m_Item1);
        
            sb.Append(")");
        
            return sb.ToString();
        
        }

          从上面的代码中可以看出几点,一是它实现了四个接口,最主要是ITuple这个接口,只要实现了这个接口,那么它就是Tuple的一个实例。第二个,我们可以看出来,它里面的元素是只读的,也就是说不能对里面的元素进行赋值,如果想得到这个元素的值,那么就直接调用对象的Item属性,Item1代表第一个元素的值,Item2代表第二个元素的值,依此类推。

          除了上面的八种Tuple类,Tuple还有一个静态类,在这个静态类里面有一个Create方法,这个方法有8种重载,下面看一下静态的Tuple类:

    public static class Tuple
        
    {
        
        public static Tuple<T1> Create<T1>(T1 item1)
        
        {
        
            return new Tuple<T1>(item1);
        
        }
        
        public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2)
        
        {
        
            return new Tuple<T1, T2>(item1, item2);
        
        }
        
        public static Tuple<T1, T2, T3> Create<T1, T2, T3>(T1 item1, T2 item2, T3 item3)
        
        {
        
            return new Tuple<T1, T2, T3>(item1, item2, item3);
        
        }
        
        public static Tuple<T1, T2, T3, T4> Create<T1, T2, T3, T4>(T1 item1, T2 item2, T3 item3, T4 item4)
        
        {
        
            return new Tuple<T1, T2, T3, T4>(item1, item2, item3, item4);
        
        }
        
        public static Tuple<T1, T2, T3, T4, T5> Create<T1, T2, T3, T4, T5>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5)
        
        {
        
            return new Tuple<T1, T2, T3, T4, T5>(item1, item2, item3, item4, item5);
        
        }
        
        public static Tuple<T1, T2, T3, T4, T5, T6> Create<T1, T2, T3, T4, T5, T6>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6)
        
        {
        
            return new Tuple<T1, T2, T3, T4, T5, T6>(item1, item2, item3, item4, item5, item6);
        
        }
        
        public static Tuple<T1, T2, T3, T4, T5, T6, T7> Create<T1, T2, T3, T4, T5, T6, T7>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7)
        
        {
        
            return new Tuple<T1, T2, T3, T4, T5, T6, T7>(item1, item2, item3, item4, item5, item6, item7);
        
        }
        
        public static Tuple<T1, T2, T3, T4, T5, T6, T7, Tuple<T8>> Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8)
        
        {
        
            return new Tuple<T1, T2, T3, T4, T5, T6, T7, Tuple<T8>>(item1, item2, item3, item4, item5, item6, item7, new Tuple<T8>(item8));
        
        }
        
        internal static int CombineHashCodes(int h1, int h2)
        
        {
        
            return (h1 << 5) + h1 ^ h2;
        
        }
        
        internal static int CombineHashCodes(int h1, int h2, int h3)
        
        {
        
            return Tuple.CombineHashCodes(Tuple.CombineHashCodes(h1, h2), h3);
        
        }
        
        internal static int CombineHashCodes(int h1, int h2, int h3, int h4)
        
        {
        
            return Tuple.CombineHashCodes(Tuple.CombineHashCodes(h1, h2), Tuple.CombineHashCodes(h3, h4));
        
        }
        
        internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5)
        
        {
        
            return Tuple.CombineHashCodes(Tuple.CombineHashCodes(h1, h2, h3, h4), h5);
        
        }
        
        internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6)
        
        {
        
            return Tuple.CombineHashCodes(Tuple.CombineHashCodes(h1, h2, h3, h4), Tuple.CombineHashCodes(h5, h6));
        
        }
        
        internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7)
        
        {
        
            return Tuple.CombineHashCodes(Tuple.CombineHashCodes(h1, h2, h3, h4), Tuple.CombineHashCodes(h5, h6, h7));
        
        }
        
        internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7, int h8)
        
        {
        
            return Tuple.CombineHashCodes(Tuple.CombineHashCodes(h1, h2, h3, h4), Tuple.CombineHashCodes(h5, h6, h7, h8));
        
        }

       所以我们在使用的时候,可以有两种方式,一种是通过创建Tuple对象,另外一种就是通过静态类的Create方法。下面看一下具体的使用示例:

    //Tuple中的值都是只读的,只能通过构造函数赋值
        
     
        
    //创建一个元素的Tuple元组
        
    Tuple<int> tuple = new Tuple<int>(5);
        
    //Tuple<int> tuple = Tuple.Create(5);//等同于第一种方式
        
    int a = tuple.Item1;
        
     
        
    //创建三个不同类型的元组
        
    Tuple<int, string, float> t = new Tuple<int, string, float>(1,"Tom",99.85f);
        
    //Tuple<int, string, float> t = Tuple.Create(1, "Tom", 99.85f);//等同于第一种方式
        
    int grade = t.Item1;
        
    string name = t.Item2;
        
    float score = t.Item3;
        
     
        
    //还可以定义Tuple的集合
        
    List<Tuple<int, string, float>> tupleList = new List<Tuple<int, string, float>>();

        看了上面的用法,是不是觉得很方便,不过还有一点需要注意的是,如果想创建8个元素的Tuple,可以使用下面的方法:

    Tuple<int, int, int, int, int, int, int, Tuple<int>> tu1 = new Tuple<int, int, int, int, int, int, int, Tuple<int>>(1,2,3,4,5,6,7,new Tuple<int>(8));

         因为最后一个元素必须是ITuple类型的,所以在使用的时候一定要小心。如果用下面的这种方式就会报错:

    //使用的时候会报错,因为最后一个参数必须是Tuple实例类型的
        
    var tu2 = new Tuple<int, int, int, int, int, int, int, int>(1, 2, 3, 4, 5, 6, 7,8);

         可以看一下它的构造函数里面是怎样实现的:

    public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, TRest rest)
        
    {
        
        if (!(rest is ITuple))
        
        {
        
            throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleLastArgumentNotATuple"));
        
        }
        
        this.m_Item1 = item1;
        
        this.m_Item2 = item2;
        
        this.m_Item3 = item3;
        
        this.m_Item4 = item4;
        
        this.m_Item5 = item5;
        
        this.m_Item6 = item6;
        
        this.m_Item7 = item7;
        
        this.m_Rest = rest;
        
    }

         它在构造函数里面经过了判断,如果不是ITuple类型就会抛出异常。不过可以使用静态Tuple类的Create方法来创建,代码如下:

    //使用静态Tuple类的Create方法,最后一个参数不需要是Tuple类型的
        
    var tu3 = Tuple.Create<int, int, int, int, int, int, int, int>(1,2,3,4,5,6,7,8);

         究其所以然,来看看Create方法里面有什么诡异之处:

    public static Tuple<T1, T2, T3, T4, T5, T6, T7, Tuple<T8>> Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8)
        
    {
        
        return new Tuple<T1, T2, T3, T4, T5, T6, T7, Tuple<T8>>(item1, item2, item3, item4, item5, item6, item7, new Tuple<T8>(item8));
        
    }

         可以看出,实际上第八个参数也需要是ITuple类型的,只不过是它在内部帮助我们转换了而已。

         Tuple介绍完了,是不是觉得很有用呢,赶快在你的程序中体验一下吧。

  • 相关阅读:
    hdu 3666 差分约束系统
    hdu 1198农田灌溉
    常微分方程(阿諾爾德) Page 45 相空間,相流,運動,相曲線 註記
    高等微積分(高木貞治) 1.4節 例2
    常微分方程(阿諾爾德) Page 45 相空間,相流,運動,相曲線 註記
    解析函數論 Page 29 命題(2) 函數模的有界性
    高等微積分(高木貞治) 1.4節 例2
    解析函數論 Page 29 命題(1) 有界閉集上的一致連續性
    解析函數論 Page 29 命題(3) 模的下界的可達性
    解析函數論 Page 29 命題(2) 函數模的有界性
  • 原文地址:https://www.cnblogs.com/lsyyx/p/4044897.html
Copyright © 2011-2022 走看看