C#自学笔记:协变和逆变

协变和逆变

  1. 协变:和谐的变化
    • 因为里氏替换原则父类可以装子类
    • 所以子类变成父类
    • 比如 string 变成 object
  2. 逆变:逆常规的变化
    • 因为里氏替换原则父类可以装子类,但是子类不能装父类
    • 所以父类变成子类
    • 比如 object 变成 string
  3. 协变和逆变是用来修饰泛型的
    1. 协变:out
    2. 逆变:in
    • 用于在泛型中修饰泛型字母的,只有泛型接口和泛型委托能使用

作用

  1. 返回值和参数
    • 用out修饰的泛型只能作为返回值
    • delegate T TestOut<out T>();
    • 用in修饰的泛型只能作为参数
    • delegate void TestIn<in T>(T t);
  2. 结合里氏替换原则理解
delegate T TestOut<out T>();
delegate void TestIn<T>(in T t);

class Father
{
}
class Son : Father
{
}

//使用
//协变,父类被子类替换	son -> father
TestOut<Son> outSon = () =>
{
    return new Son();
};
TestOut<Father> outFather = outSon;
Father father = outFather();//实际上返回的是outSon里面装的函数,返回的是Son
Father father = (Father)outFather();//最终执行结果

//逆变,子类被父类替换	father -> son;
TestIn<Father> inFather = (value) =>
{
};
TestIn<Son> inSon = inFather;
inSon(new Son());//实际上调用的是inFather,传入的参数是Son,但由于value的类型是T
                 //所以调用inFather时要将Father转化为Son

主要作用是自动识别委托的泛型之间是否有继承关系,子类东西比父类多,所以在作返回值和参数的时候有不同的特性

TestIn<Father> inFather = Fun;

void Fun(Father value)
{
};
//Father -> Son,再调用函数

TestIn<Son> inSon = inFather;
inSon(new Son()); 

简单说法:out是把子类装进成父类然后输出,in是把父类as成子类然后传进来使用

posted @ 2025-08-10 18:33  柠凉w  阅读(5)  评论(0)    收藏  举报