详解.NET 4.0中的类型和元组

原创
开发 后端
微软最新的.NET框架4.0版本开发库中包括了通用元组类,希望通过本文能帮助大家更加了解.NET 4.0。

【51CTO独家特稿】在.NET 4.0框架中元组是一组属性,为了你提供了一种更容易将数据块拼凑在一起的方法,而不必编写自己的类。有不同大小的元组,从一个单一类型属性的元组Tuple(Of T1)到有八个或更多类型的元组。例如,双重和三重元组的类型定义缩写看起来象下面这样。51CTO曾报道过《.NET 4.0中任务与线程关系谈

  1. Class Tuple(Of T1, T2)  
  2.    ReadOnly Property Item1 As T1  
  3.    ReadOnly Property Item2 As T2  
  4.    ...  
  5. End Class 
  6.  
  7. Class Tuple(Of T1, T2, T3)  
  8.    ReadOnly Property Item1 As T1  
  9.    ReadOnly Property Item2 As T2  
  10.    ReadOnly Property Item3 As T3  
  11.    ...  
  12. End color=#006699>Class 

三重元组(Tuple(Of T1, T2, T3))允许你分组三个不同的任意类型的数据块:你可以存储三个字符串,或者一个字符串、一个整数和一个日期等组合。元组的名称据说来自序列:如单,双,三,四,五,六,七,八….n元组。在编程语言,如Python和F#中,你会发现也有元组,现在在.NET 4.0的mscorlib库中也有元组了,在未来你可能会在Visual Basic(VB)和C#代码中发现它们的踪迹。

因为元组的数据属性是只读的,.NET中的元组被认为是不可修改的,如果你要修改一个值,必须创建另一个元组。要创建一个新的元组,你可以指定泛型参数类型,然后将数据值传递给构造函数。

  1. Dim person As New Tuple
  2. (Of StringStringDate) ("John""Citizen", #1/1/1980#) 

一个简单的语法是在元组类上使用Create工厂方法,并利用VB的类型推断:

  1. Dim person = Tuple.Create("John""Citizen",#1/1/1980#) 

调用Tuple.Create依赖于类型推断,如果没有类型推断,你必须编写自己的方法进行调用,并需要明确泛型参数,这样就完成否决了Share工厂方法的优势。

  1. Dim person As Tuple(Of StringStringDate)
  2.  = tuple.Create("John""Citizen", #1/1/1980#) 

注意,即使类型推断选项被关闭了 ,调用Create方法时仍然不需要指定泛型参数。

使用元组的一个问题是你的代码变得不好描述,因为元组没有描述属性名称,如person.Item1和person.Item2,在你的项目中快速添加一个简单类定义会更有意义,在Visual Studio 2010中创建一个简单的类比以前容易多了。

以我们的Person类和FirstName,LastName和DateOfBirth字段为例,在VB 10中,你可以使用自动属性减少代码量。

  1. Class Person  
  2.     Property FirstName As String  
  3.     Property LastName As String  
  4.     Property DateOfBirth As Date  
  5. End Class 

你不用再为一个属性声明后备字段,如getter和setter块,只需要属性名和它的类型即可。

VB和C#中的自动属性有很大的不同,在VB和C#中,编译器生成后备字段,以及与属性相关的get和set代码块,C#为后备字段产生一个名字,但在你的代码中却不能使用它,而在VB却允许你访问这些后备字段。以FirstName属性作为例子,在C#中后备字段名字可能是k__BackingField,由于有尖括号,因此它会被认为是非法的,而VB会产生一个后备字段named _FirstName。

在VB语言规范中明确指出可以通过名字可以访问后备字段,因此你可以放心使用,它是安全的,一个很好的例子是当添加一个参数到你类的构造函数中时,在VB中这是一个非常简单的任务。

  1. Sub New(ByVal firstName As String, _   
  2.           ByVal lastName As String, _  
  3.           ByVal dateOfBirth As Date)  
  4.       _FirstName = firstName  
  5.       _lastName = lastName  
  6.       _dateOfBirth = dateOfBirth  
  7.   End Sub 

要在C#中实现同样的功能,你必须将所有自动属性修改为标准属性,并自行声明后备字段,并在后备字段上添加get和set代码块。

注意在VB中的代码实际上是不需要逗号后面的连接符“_”,我这么做只是为了使代码更易读。

Visual Studio IDE也可以帮你生成类,它们的属性和构造函数,如果你的代码引用了一个不存在的类型,会有错误更正功能帮助你生成类。

  1. Dim person As New _  
  2.   Person(FirstName:="John",  
  3.     LastName:="Citizen",   
  4.     DateOfBirth:=#1/1/1980#) 

错误更正功能为你生成了Person类,包括一个参数的构造函数。生成的代码如下:

  1. Class Person  
  2.     Private _lastName As String 
  3.     Private _dateOfBirth As Date 
  4.     Private _firstName As String 
  5.  
  6.     Sub New(ByVal FirstName As String, _  
  7.              ByVal LastName As String, _   
  8.              ByVal DateOfBirth As Date)  
  9.         _firstName = FirstName  
  10.         _lastName = LastName  
  11.         _dateOfBirth = DateOfBirth  
  12.     End Sub 
  13. End Class 

如果你现在退回去使用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方法简化你的代码

  1. Private _propChangedEvents As New List(  
  2.             Of Tuple(Of PropertyChangedEventHandler,   
  3.                                  SynchronizationContext))  
  4.  
  5.  
  6. Public Custom Event PropertyChanged As _  
  7.                          PropertyChangedEventHandler Implements   
  8.                          INotifyPropertyChanged.PropertyChanged  
  9.     AddHandler(ByVal value As _ PropertyChangedEventHandler)  
  10.        _propChangedEvents.Add(Tuple.Create(value,   
  11.                                          SynchronizationContext.Current))  
  12.     End AddHandler 
  13.  
  14.     RemoveHandler(ByVal value As _ PropertyChangedEventHandler)  
  15.       For i As Int32 = _propChangedEvents.Count - 1 To 0 Step -1  
  16.             If _propChangedEvents(i).Item1 = value Then 
  17.                 _propChangedEvents.RemoveAt(i)  
  18.                 Return 
  19.             End If 
  20.         Next 
  21.     End RemoveHandler 
  22.  
  23.     RaiseEvent(ByVal sender As Object,  
  24.                         ByVal e As PropertyChangedEventArgs)  
  25.         For Each listener In _propChangedEvents  
  26.             If listener.Item2 Is Nothing Then 
  27.                 ' no context so raise the event directly  
  28.                 listener.Item1.Invoke(sender, e)  
  29.             Else 
  30.                 Dim oneListener = listener  
  31.                 listener.Item2.Post(Sub(state As Object)  
  32.                                      oneListener.Item1.Invoke(sender, e)  
  33.                                 End Sub,  
  34.                                 Nothing)  
  35.             End If 
  36.         Next 
  37.     End RaiseEvent 
  38. End Event 

虽然元组看起来可能比较简单和优点不伦不类的样子,但它提供了强大的类型和重要的比较功能,元组在跨方法、类甚至机器边界时非常有用,合理地使用它们将会节省你大量的编码时间。

原文出处:http://visualstudiomagazine.com/Articles/2009/12/01/Types-and-Tuples-in-NET-4.aspx

原文名:Types and Tuples in .NET 4

作者:Bill McCarthy

责任编辑:彭凡 来源: 51CTO
相关推荐

2009-03-23 10:54:12

.NET契约式编程编程思想

2009-10-26 09:16:08

BigInteger类

2009-07-24 10:00:38

.NET 4.0内存映

2009-12-28 10:04:59

.NET 4.0数组

2010-01-05 09:26:13

.NET 4.0

2021-01-13 05:18:50

数据类型性能

2009-02-03 09:33:26

动态类型动态编程C# 4.0

2009-03-04 09:52:35

代码契约组件接口

2010-07-02 09:25:37

.NET 4.0可扩展

2009-12-18 09:38:27

.NET 4.0并行计

2009-12-30 10:21:36

.NET 4.0

2011-06-08 13:50:39

C#类型转换

2023-06-30 17:56:31

Scala元组

2013-08-21 17:09:03

.Net属性

2009-10-20 15:03:29

ExpandoObje

2010-01-14 14:12:14

Visual Stud

2009-07-10 09:41:08

WCF服务配置.NET 4.0

2010-05-20 08:50:45

UrlRoutingASP.NET 4.0

2009-08-17 09:30:28

.NET 4.0

2009-06-03 14:50:17

C# 4.0泛型协变性
点赞
收藏

51CTO技术栈公众号