使用泛型时,避免基类及接口约束
使用泛型的时候我们可以这样来约束一个参数
void Sort<T>(T[] arr) where T : IComparable<T>
这里实现一个泛型的排序方法,约束参数T必须是实现 IComparable<T>接口,那么当我们使用这个方法的时候,
我们不得不提供满足约束的参数,否则在强制转换的时候就会报错,那么当我们或者使用者原有的对象类
型并非实现IComparable<T>的时候呢?为了排序,我们不得不修改原来的对象,让它实现约束的接口,
一般看来,这个方法做了很好的规范,
然而实际应用中,这个方法是很不合适的,首先为什么非要实现了
IComparable<T>接口的对象才能进行排序?实现了IComparable的就不行吗?没有实现二者中任何一个的接口对象
就不行排序吗?这个约束几乎把所有普通类型的对象拒之门外~ 然而我们仅仅需要的只是一个比较方法~
再看看这个方法:
void Sort<T>(T[] arr, IComparer<T> comparer)
现在我们对T现在没有任何限制,但是要求提供一个IComparer(Of T)的实例。这个IComparer(Of T)的实现和T可
以没有关系,因此不仅T可以不知晓它的存在,还可以提供不只一种的比较方法。
再改进一下:
void Sort<T>(T[] arr){Sort(arr, Comparable<T>.Default);}
代码中的Comparer(Of T)是System.Collection.Generic下的一个类型,专门用于提供类型默认的比较器。
我们现在没有约束了,但是对用户来说,和有约束时的语法一样简单而清晰。比较那些实现了IComparable
和IComparable(Of T)的类型时,Comparer(Of T)都提供了支持,而在比较没有实现这类接口的自定义类型时,
可自行实现IComparer(Of T)提供比较机制。完美解决。
这种方法还能进行一些约束都实现不了的做法:支持运算符。我们知道在类型参数上实现哪怕最简单的加法都是不允许的,
而且没有任何接口可以帮你做到这一点。这时如果能够使用外部辅助类的做法,就能够突破这一恼人的限制。
下面是VBF中来计算类型参数的加法
T Add<T>(T a, T b, ICalculator<T> calc)
{
return calc.Add(a, b);
}
T Add<T>(T a, T b)
{
return Calculator<T>.Default.Add(a, b);
}
学习泛型,能从一个新的角度来思考问题的解决方法 (个人理解加转载)