为什么这个要用泛型约束来实现接口

我在学习C#时 参考果壳中的C# 5.0 一书
书中谈到了泛化约束的问题时 说道 “基类约束或接口约束规定类型参数必须是某个类的子类或实现特定类或接口。” 然后讲了一个例子:
这个是框架中定义的泛化接口IComparable<T>

public interface IComparable<T>
{
    int CompareTo(T other); 
}

如果other 比 this 大compareTo方法就会返回正值。

static T Max<T> (T a,T b) where T : Icomparable<T>
{
    return a.CompareTo(b) > 0? a:b;
}

int z = Max(5,10);  // 10
string last  = Max("ant","zoo"); //zoo

由于我不是很理解上面说道的
“基类约束或接口约束规定类型参数必须是某个类的子类或实现特定类或接口。”
所以不是很懂这个例子想表达什么,为什么不可以直接实现这个接口,一定要用接口约束呢?
我试过直接实现接口,但是IDE会报错,不是很懂,还是请诸位来帮一手吧。

阅读 5.8k
2 个回答
static T Max<T> (T a,T b) where T : Icomparable<T>
{
    return a.CompareTo(b) > 0? a:b;
}

里的where部分是接口约束,T必须实现Icomparable<T>接口。

为什么要这个约束?因为Max的参数a要支持CompareTo方法,所以a必须实现Icomparable<T>接口。

实现接口和某个方法使用泛型约束面向的是不同场景,并没有替代性。如上述例子中:

  • 将类实现IComparable<T>表示的是这个类的实例之间可以使用CompareTo方法进行比较;

  • 而在类中提供Max<T>这个方法表示的是可以使用该类对两个IComparable<T>实例进行取较大值的操作;

根本是不相干的目的。换句话,让类实现接口并不能让它具备Max方法的能力,反过来,在类中编写一个处理其它类型的方法不表示类本身要跟这些类型扯上关系。

如果你疑惑的是:

本来可以让类实现IComparable<T>,这样就不用在编写Max方法时再用泛型约束这么啰嗦,为什么不这样处理

的话,原因有:

  1. 会造成污染。试想这个类仅仅有Max这个方法处理T,其余成员都跟T没关系,那你让整个类泛型化后,在使用该类时就得指定一个T,哪怕目的只是使用类中的其它方法而不是Max,也不得不塞一个毫无意义的T进来。比如类中还有另一个实用函数Foo(string s),为了使用它,不得不这样Class<Shit>.Foo("asdf"),这个Shit完全是多余的东西

  2. 会很扯蛋。假如Foo函数也是处理泛型而不是string,但它接受的泛型与Max的T并无关联,于是只能这样定义Foo(T2 t),好了,现在类里面有MaxFoo两个方法接受不同的泛型,为了不使用方法级的泛型约束,只能在类级这样定义Class<T, T2>,恭喜,以后不管调用啥,要想使用这个类都得塞进俩类型,Class<Shit, Fuck>.Whatever();如果类中再来个Foo2(T3 t)呢?显然,这样使用:

    Class.Max<int>();
    Class.Foo<string>();
    Class.Foo2<double>();
    Class.Whatever();

    才是优雅的。

总结起来就是,当泛型与类的关系不大,而只与其中少量方法有关的话,就该把方法进行泛型化,而不是把整个类泛型化。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进