概述

  • 协变性: 子类到父类的转换(如:string->object).
  • 逆变性: 父类到子类的转换(如:object->string).
  • 协变性指定返回类型的兼容性,而逆变性指定参数的兼容性.

委托的协变与逆变

代码示例

协变
逆变
// 基类
class Animal
{
    public int Legs = 4;
}

// 派生类
class Dog : Animal
{

}

// Factory 委托
delegate T Factory<out T>();

class Program
{
    static Dog MakeDog()
    {
        return new Dog();
    }

    static void Main(string[] args)
    {
        // 创建派生类型的委托
        Factory<Dog> dogMaker = MakeDog;
        // 派生类型构造的委托转为基类型构造的委托
        Factory<Animal> animalMaker = dogMaker;
        Console.WriteLine(animalMaker().Legs.ToString());
    }
}

接口的逆变与协变

代码示例

协变
逆变
interface IFoo<out T>
{
    T GetName();
}

class Foo : IFoo<string>
{
    public string GetName()
    {
        return GetType().Name;
    }
}

class Program
{
    static void Main(string[] args)
    {
        IFoo<string> fooStr = new Foo();
        IFoo<object> fooObj = fooStr;

        // IFoo<object> 需要 object 的返回类型.
        // new Fool().GetName() 方法返回类型是 string 类型. string 类型转化为 object 类型.
        object memberName = fooObj.GetName();
        Console.WriteLine(memberName);
        Console.Read();
    }
}
interface IFoo<in T>
{
    void Print(T content);
}

class Foo : IFoo<object>
{
    public void Print(object content)
    {
        Console.WriteLine(content);
    }
}

class Program
{
    static void Main(string[] args)
    {
        IFoo<object> fooObj = new Foo();
        IFoo<string> fooStr= fooObj;

        // new Fool().Print() 方法输入参数是 object 类型.
        // fooStr.Print() 方法输入参数是 string 类型. 隐式将 string 转化为 object.
        fooStr.Print("Hello World");
        Console.Read();
    }
}

代码示例

参考链接

  1. 协变与逆变