图文详解C#中的协变与逆变
什么是协变与逆变
协变和逆变是指可以使用派生类型来代替基类型的能力。协变用于返回值类型,逆变用于参数类型。在C#中,协变和逆变可以应用于委托(delegate)和泛型(generic)类型。
协变
协变可用于返回类型,指一个方法返回类型可以使用它继承的类型。使用out关键字可实现协变。
示例1
class Program
{
static void Main(string[] args)
{
IAnimalContainer<Cat> catContainer = new AnimalContainer<Cat>();
IAnimalContainer<Animal> animalContainer = catContainer;
Console.WriteLine(animalContainer.GetType()); //输出AnimalContainer`1
Console.ReadKey();
}
}
interface IAnimalContainer<out T>
{
T GetAnimal();
}
class AnimalContainer<T> : IAnimalContainer<T> where T : Animal, new()
{
public T GetAnimal()
{
Console.WriteLine("Create a {0}", typeof(T).Name);
return new T();
}
}
class Animal
{
}
class Cat : Animal
{
}
上面代码片段中定义了三个类Animal
、Cat
和AnimalContainer<T>
。Animal
和Cat
是继承关系,AnimalContainer<T>
为泛型接口IAnimalContainer<T>
的实现类,并且AnimalContainer<T>
类中的T
的限制为继承Animal
,并且具有默认公共构造函数。
在Main
方法中,我们定义了两个对象catContainer
和animalContainer
,分别是IAnimalContainer<Cat>
和IAnimalContainer<Animal>
类型的,catContainer
对象是具体类型AnimalContainer<Cat>
的实例。然后我们将catContainer
赋值给animalContainer
,由于out
关键字的使用,这行代码是合法的,可以成功编译。
最后我们输出了animalContainer
对象的类型,结果是AnimalContainer
,即像我们预期的类型成功变成了它的基类类型。这就是协变的示例。
逆变
逆变用于参数类型,表示一个方法的参数可以使用其基类型。使用in关键字可实现逆变。
示例2
class Program
{
static void Main(string[] args)
{
IAnimalTracker<Cat> catTracker = new CatTracker();
IAnimalTracker<Animal> animalTracker = catTracker;
animalTracker.Track(new Animal());
Console.ReadKey();
}
}
interface IAnimalTracker<in T>
{
void Track(T animal);
}
class CatTracker : IAnimalTracker<Cat>
{
public void Track(Cat cat)
{
Console.WriteLine("Tracking a cat");
}
public void Track(Animal animal)
{
Console.WriteLine("Tracking an animal");
}
}
class Animal
{
}
class Cat : Animal
{
}
上面代码片段中定义了三个类Animal
、Cat
和CatTracker
,Animal
和Cat
是继承关系,CatTracker
为泛型接口IAnimalTracker<T>
的实现类,并且IAnimalTracker<T>
中的T
使用in
关键字实现逆变。
在Main
方法中,我们定义了两个对象catTracker
和animalTracker
,分别是IAnimalTracker<Cat>
和IAnimalTracker<Animal>
类型的,catTracker
对象是具体类型CatTracker
的实例。然后我们将catTracker
赋值给animalTracker
,由于in
关键字的使用,这行代码是合法的,可以成功编译。
最后我们对animalTracker
对象执行了Track
方法,并且传入了一个具体类型为Animal
的对象,运行结果仍然是Tracking a cat
,我们传入的具体类型为Animal
的参数成功转换为基类型Cat
,这就是逆变的示例。
结论
协变和逆变是C#中非常有用的特性,可用于泛型和委托中。协变可用于返回类型,逆变可用于参数类型。当一个类型可以被替换为他的基类型或者继承类型时,我们可以使用协变或逆变。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:图文详解C#中的协变与逆变 - Python技术站