[微软] 元组类型
[微软] System.Tuple
[微软] System.ValueTuple
// 这是最简单的: [Serializable] public class Tuple<T1> { private T1 m_Item1; public Tuple(T1 item1) { m_Item1 = item1; } public T1 Item1 { get { return m_Item1; } } }// 这是最复杂的 [Serializable] public class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> { private T1 m_Item1; private T2 m_Item2; private T3 m_Item3; private T4 m_Item4; private T5 m_Item5; private T6 m_Item6; private T7 m_Item7; private TRest m_Rest; public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, TRest rest) { m_Item1 = item1; m_Item2 = item2; m_Item3 = item3; m_Item4 = item4; m_Item5 = item5; m_Item6 = item6; m_Item7 = item7; m_Rest = rest; } public T1 Item1 { get { return m_Item1; } } public T2 Item2 { get { return m_Item2; } } public T3 Item3 { get { return m_Item3; } } public T4 Item4 { get { return m_Item4; } } public T5 Item5 { get { return m_Item5; } } public T6 Item6 { get { return m_Item6; } } public T7 Item7 { get { return m_Item7; } } public TRest Rest { get { return m_Rest; } } }
和匿名类型相似,Tuple创建好之后就不可变了(所有属性都只读)。虽然这里没有显示,但Tuple类还提供了CompareTo,Equals,GetHashCode和ToString方法以及Size属性。此外,所有Tuple类型都实现了IStructuralEquatable,IStructuralComparable和IComparable接口,所以可以比较两个Tuple对象,对它们的字段进行比对。
// 用Item1返回最小值,用Item2返回最大值 private static Tuple<Int32, Int32> MinMax(Int32 a, Int32 b) { return new Tuple<Int32, Int32>(Math.Min(a,b), Math.Max(a,b));//也可以用Create方法创建Tuple //return Tuple.Create(Math.Min(a,b), Math.Max(a,b)); }// 下面展示如何调用方法,以及如何使用返回的Tuple private static void TupleTypes() { var minmax = MinMax(6, 2); Console.WriteLine("Min={0}, Max={1}", minmax.Item1, minmax.Item2); }
// 要创建多于8个元素的Tuple,可为Rest参数传递另一个Tuple var t = Tuple.Create(0,1,2,3,4,5,6, Tuple.Create(7,8)); Console.WriteLine("{0},{1},{2},{3},{4},{5},{6},{7},{8}", t.Item1, t.Item2, t.Item3, t.Item4, t.Item5, t.Item6, t.Item7, t.Rest.Item1.Item1, t.Rest.Item1.Item2);
除了匿名类型和Tuple类型,还可以研究一下System.Dynamic.ExpandoObject类(在System.Core.dll程序集中定义)。这个类和C#的dynamic类型配合使用,就可用另一种方式将一系列属性(键/值对)组合到一起。虽然实现不了编译时的类型安全性,但语法看起来不错(虽然得不到“智能感知”支持),而且还可以在C#和Python这样的动态语言之间传递ExpandoObject对象。以下是使用了一个ExpandoObject的示例代码:
dynamic e = new System.Dynamic.ExpandoObject(); e.x = 6;//添加一个Int32 ‘x’属性,其值为6 e.y = "Jeff";//添加一个String ‘y’属性,其值为"Jeff" e.z = null;//添加一个Object ‘z’属性,其值为null //查看所有属性及其值 foreach (var v in (IDictionary<String, Object>)e) Console.WriteLine("Key={0}, V={1}", v.Key, v.Value);//删除'x'属性及其值 var d = (IDictionary<String, Object>)e; d.Remove("x");