抗变

  要把泛型类型参数定义为抗变,可在类型定义中使用in关键字:

  1. public interface IGrassMuncher<in T>
  2. {
  3. ...
  4. }

  对于接口定义,抗变类型参数只能用作方法参数,不能用作返回类型。

  理解这一点的最佳方式是列举一个在.NET Framework中使用抗变的例子。带有抗变类型参数的一个接口是前面用过的IComparer<T>。可以给Animal实现这个接口,如下所示:

  1. public class AnimalNameLengthComparer : IComparer<Animal>
  2. {
  3. public int Compare(Animal x, Animal y)
  4. {
  5. return x.Name.Length.CompareTo(y.Name.Length);
  6. }
  7. }

  这个比较器按名称的长度比较动物,所以可以使用它对List<Animal>的实例排序。通过抗变,还可以使用它对List<Cow>的实例排序,尽管List<Cow>.Sort()方法需要IComparer<Cow>的实例。

  这个比较器按名称的长度比较动物,所以可以使用它对List<Animal>的实例排序。通过抗变,还可以使用它对List<Cow>的实例排序,尽管List<Cow>.Sort()方法需要IComparer<Cow>的实例。

  1. List<Cow> cows = new List<Cow>();
  2. cows.Add(new Cow("Geronimo"));
  3. cows.Add(new SuperCow("Tonto"));
  4. cows.Add(new Cow("Gerald"));
  5. cows.Add(new Cow("Phil"));
  6. cows.Sort(new AnimalNameLengthComparer());

  大多数情况下,抗变都会发生—-它被添加到.NET Framework中就是为了帮助执行这种操作。.NET 4及更高版本中这两种变体的优点是,你可以在需要时使用本节介绍的技术实现它。