前一段时间我介绍了泛型,其中有个很重要的特性叫“约束”。使用约束,可以减小泛型类型参数的取值范围,同时能够允许在泛型类型上应用所约束类型的功能。许多人为了在泛型类型上进行所需的操作,约束大量的类型。事实上,我觉得没有特别要求,泛型的类型参数应该尽量不约束任何类型,因为它会严重缩小你的泛型类的使用范围。而在类型参数上进行操作着一需求,并不是只能通过约束来达成。
规则:当你希望对类型参数实施的操作只用于你的泛型类一部分功能时,用辅助对象代替约束。
比如你希望编写一个容器类,它有很多功能,其中一个是排序。排序需要对象之间进行比较。如果容器类的其他功能并不依赖于排序,那么对整个类的类型参数使用约束就不合适。因为我们有可能根本不用排序,为什么还要有此约束呢。比如你将类写成:
Public Class MyContainer(Of T As IComparable(Of T))
Public Sub Sort()
Dim a, b As T
If a.CompareTo(b) Then
'code
End If
End Sub
End Class
那么T所能取值的范围就大大减少了。我们不妨让用户在需要排序的时候,自行指定比较的依据,而不是强迫类型自己必须能够比较大小。改动成这样:
Public Class MyContainer(Of T)
Public Sub Sort(ByVal compareHelper As Comparison(Of T))
Dim a, b As T
If compareHelper(a, b) Then
'code
End If
End Sub
End Class
这里,compareHelper就充当了辅助对象的功能。辅助对象是独立于类型T之外的,因此T不需要进行任何约束。而用户则必须为该功能提供正确的辅助对象。将辅助对象设置为委托是相当好的,这样用户可以只编写一个方法来规定辅助对性的功能(而不用编写一个完整的类)。C#用户甚至可以用匿名方法就地指定辅助对象的功能。.NET Framework为我们头提供了几个常用的泛型委托,都可以用作辅助对象的类型:
System.Action(Of T) '是一个无返回值的方法,用于进行作用于一个T对象的动作
System.Comparison(Of T) '用于比较了两个T类型的对象
System.Converter(Of T, U) '用于指定将一个T对象转成U类型的规则
System.Predicate(Of T) '用于指定T类型的一个对象是否符合某项判断
当然,我们很容易就可以指定自己的辅助对象类型。不仅仅是委托,还可以是更加复杂的功能。用辅助对象代替约束,可以确保你的泛型类型有最大的应用范围,同时能让用户对特定的功能做深层次的定制。那什么时候用约束?当你的类确实只对某一类对象起作用,换句话说,你想要类型参数具有的功能贯穿整个泛型类的设计,那么约束就是更好的选择了。
打印 | 张贴于 2005-01-04 18:05:00 | Tag:技术随笔 灵感记录
留言反馈