public class Test : MonoBehaviour
{
    //协变,out修饰返回值
    public delegate T Function<out T>();
    //逆变,in修饰传入参数
    public delegate void Action<in T>(T t);

    public class Animal { }
    public class Dog : Animal { }

    private void Start()
    {
        //成立。方法DogFunc与委托function1的返回值类型相同
        Function<Dog> function1 = DogFunc;
        //成立。方法DogFunc的返回值是委托function2的返回值的子类,要求返回父类型时返回子类型,符合赋值兼容性的原则
        Function<Animal> function2 = DogFunc;
        //普通情况下不成立,协变下成立。
        //普通情况下,function1与function3都是delegate的子类,是同级的,没有继承关系,不符合赋值兼容性的原则
        //协变,在委托或接口中,返回值是基类时允许返回其子类,允许更高程度的子类型处于返回及输出位置
        Function<Animal> function3 = function1;

        Debug.Log(function1());     // Dog
        Debug.Log(function2());     // Dog
        Debug.Log(function3());     // Dog

        //----------

        //成立。方法AnimalAct与委托action1的参数类型相同
        Action<Animal> action1 = AnimalAct;
        //成立。委托action2的参数类型是方法AnimalAct的参数类型子类,要求传入父类型时传入子类型,符合赋值兼容性的原则
        Action<Dog> action2 = AnimalAct;
        //普通情况下不成立,逆变下成立。
        //普通情况下,action1与action3都是delegate的子类,是同级的,没有继承关系,不符合赋值兼容性的原则
        //逆变,在委托或接口中,在期望传入基类型是允许传入其子类型,允许更高程度的子类型作为输入参数
        Action<Dog> action3 = action1;

        action1(new Animal());      // Animal
        action2(new Dog());         // Dog
        action3(new Dog());         // Dog
    }

    private Dog DogFunc()
    {
        return new Dog();
    }

    private void AnimalAct(Animal animal)
    {
        Debug.Log(animal);
    }

}