协变

  要把泛型类型参数定义为协变,可以在类型定义中使用out关键字,如下面的示例所示:

  1. public interface IMethaneProducer<out T>
  2. {
  3. ...
  4. }

  对于接口定义,协变类型参数只能用作方法的返回值或属性get访问器。 ??

  说明协变用途的一个很好例子在.NET Framework中,即前面使用的IEnumerable<T>接口。在这个接口中,项类型T定义为协变,这表示可以把支持IEnumerable<Cow>的对象放在IEnumerable<Animal>类型的变量中。

  因此下面的代码是有效的:

  1. static void Main(string[] args)
  2. {
  3. List<Cow> cows = new List<Cow>();
  4. cows.Add(new Cow("Gernoimo"));
  5. cows.Add(new SuperCow("Tonto"));
  6. ListAnimals(cows);
  7. Console.ReadKey();
  8. }
  9. static void ListAnimals(IEnumerable<Animal> animals)
  10. {
  11. foreach(Animal animal in animals)
  12. {
  13. Console.WriteLine(animal.ToString());
  14. }
  15. }

  其中cows变量的类型是List<Cow>,它支持IEnumerable<Cow>接口。通过协变,这个变量可以传送给需要IEnumerable<Animal>类型的参数的方法。回顾一下froeach循环的工作方式,就知道GetEnumerator()方法用于获取IEnumerator<T>的一个枚举器,该枚举器的Current属性用于访问项。IEnumerator<T>还将其类型参数定义为协变,这表示可以把它用作参数的get访问器,而且一切都运转良好。