将来的.NET版本是否支持C#中的元组?

.Net 3.5不支持元组。 太糟糕了,但不确定未来版本的.net是否会支持元组?

我刚刚阅读了MSDN Magazine的这篇文章: Building Tuple

这里是摘录:

即将发布的4.0版本的Microsoft .NET Framework引入了一种名为System.Tuple的新types。 System.Tuple是一个固定大小的异构types数据集合。

就像一个数组一样,一个元组有一个固定的大小,一旦创build就无法更改。 与数组不同,元组中的每个元素可能是不同的types,并且元组能够保证每个元素的强types化。

在System.Collections.Generic命名空间中,已经有一个元组在Microsoft .NET Framework上浮动的示例:KeyValuePair。 虽然KeyValuePair可以被认为与Tuple相同,但是因为它们都是两种types的东西,所以KeyValuePair与Tuple有所不同,因为它唤起了它所存储的两个值之间的关系(有很好的理由,因为它支持Dictionary类)。

此外,元组可以是任意大小的,而KeyValuePair只有两个东西:一个键和一个值。


虽然像F#这样的语言对元组有特殊的语法,但是你可以使用任何语言的新的通用元组types。 重新回顾第一个例子,我们可以看到虽然有用,但元组可以在语法上过于冗长而没有元组的语法:

class Program { static void Main(string[] args) { Tuple<string, int> t = new Tuple<string, int>("Hello", 4); PrintStringAndInt(t.Item1, t.Item2); } static void PrintStringAndInt(string s, int i) { Console.WriteLine("{0} {1}", s, i); } } 

使用C#3.0中的var关键字,我们可以删除tuplevariables上的types签名,这允许更多的可读代码。

 var t = new Tuple<string, int>("Hello", 4); 

我们还添加了一些工厂方法到一个静态的Tuple类,这使得更容易用支持types推断的语言来构build元组,如C#。

 var t = Tuple.Create("Hello", 4); 
 #region tuples public class Tuple<T> { public Tuple(T first) { First = first; } public T First { get; set; } } public class Tuple<T, T2> : Tuple<T> { public Tuple(T first, T2 second) : base(first) { Second = second; } public T2 Second { get; set; } } public class Tuple<T, T2, T3> : Tuple<T, T2> { public Tuple(T first, T2 second, T3 third) : base(first, second) { Third = third; } public T3 Third { get; set; } } public class Tuple<T, T2, T3, T4> : Tuple<T, T2, T3> { public Tuple(T first, T2 second, T3 third, T4 fourth) : base(first, second, third) { Fourth = fourth; } public T4 Fourth { get; set; } } #endregion 

为了使声明更漂亮:

 public static class Tuple { //Allows Tuple.New(1, "2") instead of new Tuple<int, string>(1, "2") public static Tuple<T1, T2> New<T1, T2>(T1 t1, T2 t2) { return new Tuple<T1, T2>(t1, t2); } //etc... } 

在Lokad共享库 (当然是开放源代码)中有一个适当的 (不是快速的) C#元组实现,它包含以下所需的特性:

  • 2-5个不可变的元组实现
  • 正确的DebuggerDisplayAttribute
  • 适当的哈希和平等检查
  • Helpers用于从提供的参数中生成元组(generics是由编译器推断出来的)和基于集合操作的扩展。
  • 生产testing。

在C#中实现Tuple类或重复使用F#类只是一个故事 – 这使您能够相对容易地创build元组,但不是真正的语法糖,这使得它们非常适合在F#等语言中使用。

例如,在F#中,可以使用模式匹配来抽取let语句中的元组的两个部分,例如

 let (a, b) = someTupleFunc 

不幸的是,使用来自C#的F#类来做同样的事情会更不雅观:

 Tuple<int,int> x = someTupleFunc(); int a = x.get_Item1(); int b = x.get_Item2(); 

元组代表了一个强大的方法,可以从函数调用中返回多个值,而不需要用一次性类来抛弃代码,或者使用丑陋的引用或输出参数。 然而,在我看来,没有一些语法糖使它们的创造和访问更加优雅,它们的使用是有限的。

在我看来,匿名types的function不是一个元组,而是一个非常类似的构造。 一些LINQ查询的输出是匿名types的集合,类似于元组。

这是一个声明,它创build一个types化的元组:-)在飞行中:

 var p1 = new {a = "A", b = 3}; 

请参阅: http : //www.developer.com/net/csharp/article.php/3589916

我的开源.NET Sasa库已经有了多年的元组(以及大量的其他function,比如完整的MIMEparsing)。 我已经在生产代码中使用了好几年了。

C#通过generics很容易支持简单的元组(如前面的答案),通过“嘟嘟打字”(C#语言增强的许多可能之一)来改进types推断,它们可能非常非常强大。

对于什么是值得的,F#本地支持元组,并且玩过它,我不确定(匿名)元组增加了多less…你简短地获得的代码清晰度会很快失去。

对于单一方法中的代码,有匿名types; 对于一个方法以外的代码,我想我会坚持简单的命名types。 当然,如果未来的C#使得这些不可变的事情变得容易(虽然仍然容易处理),我会很高兴。

C#7本地支持元组:

 var unnamedTuple = ("Peter", 29); var namedTuple = (Name: "Peter", Age: 29); (string Name, double Age) typedTuple = ("Peter", 29); 

如果我记得我的计算机科学类正确的元组只是数据。

如果你想分组数据 – 创build包含属性的类。 如果你需要像KeyValuePair那样的东西,那就是了。

这里是我的一组元组,它们是由Python脚本自动生成的,所以我可能已经过了一点点:

链接到Subversion版本库

你需要一个用户名/密码,他们都是客人

它们基于inheritance,但即使它们碰巧具有相同的两个第一个成员的值, Tuple<Int32,String>也不会与Tuple<Int32,String,Boolean>进行比较。

他们也实现了GetHashCode和ToString等等,还有很多小的辅助方法。

使用示例:

 Tuple<Int32, String> t1 = new Tuple<Int32, String>(10, "a"); Tuple<Int32, String, Boolean> t2 = new Tuple<Int32, String, Boolean>(10, "a", true); if (t1.Equals(t2)) Console.Out.WriteLine(t1 + " == " + t2); else Console.Out.WriteLine(t1 + " != " + t2); 

会输出:

 10, a != 10, a, True 

我会感到惊讶 – C#是一种强types语言,而元组适合更dynamictypes的语言。 随着时间的推移,C#已经越来越具有dynamic性,但这是语法糖,而不是底层数据types的真正转变。

如果你想在一个实例中使用两个值,KeyValuePair <>是一个体面的替代品,虽然笨拙。 你也可以做一个结构或一个类来做同样的事情,并且是可扩展的。

为了使这些在散列表或字典中有用,您可能希望为GetHashCode和Equals提供重载。