【51CTO独家特稿】在.NET 4.0框架中元组是一组属性,为了你提供了一种更容易将数据块拼凑在一起的方法,而不必编写自己的类。有不同大小的元组,从一个单一类型属性的元组Tuple(Of T1)到有八个或更多类型的元组。例如,双重和三重元组的类型定义缩写看起来象下面这样。51CTO曾报道过《.NET 4.0中任务与线程关系谈》
- Class Tuple(Of T1, T2)
- ReadOnly Property Item1 As T1
- ReadOnly Property Item2 As T2
- ...
- End Class
- Class Tuple(Of T1, T2, T3)
- ReadOnly Property Item1 As T1
- ReadOnly Property Item2 As T2
- ReadOnly Property Item3 As T3
- ...
- End color=#006699>Class
三重元组(Tuple(Of T1, T2, T3))允许你分组三个不同的任意类型的数据块:你可以存储三个字符串,或者一个字符串、一个整数和一个日期等组合。元组的名称据说来自序列:如单,双,三,四,五,六,七,八….n元组。在编程语言,如Python和F#中,你会发现也有元组,现在在.NET 4.0的mscorlib库中也有元组了,在未来你可能会在Visual Basic(VB)和C#代码中发现它们的踪迹。
因为元组的数据属性是只读的,.NET中的元组被认为是不可修改的,如果你要修改一个值,必须创建另一个元组。要创建一个新的元组,你可以指定泛型参数类型,然后将数据值传递给构造函数。
- Dim person As New Tuple
- (Of String, String, Date) ("John", "Citizen", #1/1/1980#)
一个简单的语法是在元组类上使用Create工厂方法,并利用VB的类型推断:
- Dim person = Tuple.Create("John", "Citizen",#1/1/1980#)
调用Tuple.Create依赖于类型推断,如果没有类型推断,你必须编写自己的方法进行调用,并需要明确泛型参数,这样就完成否决了Share工厂方法的优势。
- Dim person As Tuple(Of String, String, Date)
- = tuple.Create("John", "Citizen", #1/1/1980#)
注意,即使类型推断选项被关闭了 ,调用Create方法时仍然不需要指定泛型参数。
使用元组的一个问题是你的代码变得不好描述,因为元组没有描述属性名称,如person.Item1和person.Item2,在你的项目中快速添加一个简单类定义会更有意义,在Visual Studio 2010中创建一个简单的类比以前容易多了。
以我们的Person类和FirstName,LastName和DateOfBirth字段为例,在VB 10中,你可以使用自动属性减少代码量。
- Class Person
- Property FirstName As String
- Property LastName As String
- Property DateOfBirth As Date
- End Class
你不用再为一个属性声明后备字段,如getter和setter块,只需要属性名和它的类型即可。
VB和C#中的自动属性有很大的不同,在VB和C#中,编译器生成后备字段,以及与属性相关的get和set代码块,C#为后备字段产生一个名字,但在你的代码中却不能使用它,而在VB却允许你访问这些后备字段。以FirstName属性作为例子,在C#中后备字段名字可能是 在VB语言规范中明确指出可以通过名字可以访问后备字段,因此你可以放心使用,它是安全的,一个很好的例子是当添加一个参数到你类的构造函数中时,在VB中这是一个非常简单的任务。 要在C#中实现同样的功能,你必须将所有自动属性修改为标准属性,并自行声明后备字段,并在后备字段上添加get和set代码块。
注意在VB中的代码实际上是不需要逗号后面的连接符“_”,我这么做只是为了使代码更易读。
Visual Studio IDE也可以帮你生成类,它们的属性和构造函数,如果你的代码引用了一个不存在的类型,会有错误更正功能帮助你生成类。
错误更正功能为你生成了Person类,包括一个参数的构造函数。生成的代码如下:
如果你现在退回去使用With {. }语法修改你的变量声明初始化属性,更正向导会建议你添加属性,虽然你可以使用通用代码功能快速创建一个类,但仍然需要自己编写属性,要么使用代码片段要么使用自动属性语法。通用代码功能的几大亮点是当你向类中增加一个方法时,你可能不想停下来,然后自己添加一个方法或属性,而是希望将注意力放在当前的代码流中,但在添加属性时应谨慎使用,因为添加属性时有很多其它代码需要修改。
#T# 在声明只读属性时,无论是通用代码功能还是自动属性都可以帮到你。为了创建一个不可修改的类,你仍然需要自己动手在Visual Studio 2010中写几行代码。
为了使你的类和元组类有相同的功能,你也需要基于你的后备字段添加同等的ToString和GetHashCode代码。ToString方法非常适合调式和测试,GetHashCode方法重点在排序、比较和字典式存储上,Equals方法也应该重写,此外,你需要实现IComparable和它的CompareTo函数以允许排序。
元组类代码已经到位,它们甚至实现了两个新的接口:IStructuralComparable 和 IStructuralEquatable。这些接口提供了CompareTo函数和一个额外的IComparer参数,以及Equals和参数为IEqualityComparer 的GetHashCode函数,它允许自定义排序。
自己动手编写所有的代码工作量非常大,至少你应该考虑将GetHashCode添加到你的类中,如果你使用代码生成功能,它会向你的类添加一个属性,你可以继续编你的码,但可以忘掉你要打开的文件,它可以修复你的GetHashCode和其它方法。
元组的优点
当你完全了解了元组后,你就会知道它的好处,尽管它们有不伦不类的Item1,Item2,Item3等属性。元组类是固定的,你不能修改它。你也不必处理跨机器边界和分布式类型信息的问题,因为在.NET 4.0中,元组在mscorlib库中,甚至还有一些不错的尝试,如TargetedPatchingOptOut属性修饰,因此允许属性是跨本地图形生成器的图像。
毫无疑问,使用元组可以减少代码量,当你在VB10中将元组和lambda表达式结合使用时,可以大大减少代码量。下面是我最近一篇文章中使用到的代码,是在VB10中完成的,但如果在VB9中代码量要多出一倍。使用元组和lambda表达式完全去除了我之前需要的PropertyChangedEventContext类。元组为事件处理程序和同步上下文提供了基本的数据存储,剩下需要做的事情是能够将事件处理程序传递给同步上下文的Post方法。
代码段1:在Visual Studio 2010中使用元组和lambda方法简化你的代码
虽然元组看起来可能比较简单和优点不伦不类的样子,但它提供了强大的类型和重要的比较功能,元组在跨方法、类甚至机器边界时非常有用,合理地使用它们将会节省你大量的编码时间。
原文出处:http://visualstudiomagazine.com/Articles/2009/12/01/Types-and-Tuples-in-NET-4.aspx
原文名:Types and Tuples in .NET 4
作者:Bill McCarthy