【C#】协变和逆变

基本概念:在 C# 中,协变和逆变能够实现数组类型、委托类型和泛型类型参数的隐式引用转换。

主要遵循的原则是里氏替换原则,即父类可以装子类。比如string变成object。

用途:协变和逆变是修饰泛型类型参数的,协变是out,逆变是in,修饰泛型类型参数,只有泛型接口和泛型委托能使用。

返回值和参数

out修饰的泛型只能作为返回值使用;

delegate T TestOut();

in修饰的泛型只能作为参数使用。

delegate void TestIn(T t);

结合里氏替换原则理解

class Father { }
class Son:Father { }
internal class Program
{
    static void Main(string[] args)
    {
        //结合里氏替换原则理解
        //里氏替换原则:父类装子类
        //协变out:修饰委托delegate泛型,只能作为返回值使用
        TestOut<Son> testOutSon = () =>
        {
            return new Son();
        };
        //委托是装“格式相同”的函数,如果不用out,此处代码会报错。因为TestOut<Father>和TestOut<Son>的泛型不同。
        //但实际上TestOut<Father>泛型是Father类,TestOut<Son>泛型是Son类,即泛型存在一个父子关系,
        //所以,使用out修饰委托delegate的泛型,系统会自己判断返回值是否存在父子关系,即是否可以使用里氏替换原则。
        //那么,实际执行TestOut<Father>时,返回值是Son,是Father的子类,满足里氏替换原则,
        //所以,存在父子关系的,且用out修饰委托泛型的可以使TestOut<Father>装TestOut<Son>。
        TestOut<Father> testOutFather = testOutSon;
        Father father = testOutFather();
        //逆变in:修饰委托delegate泛型,只能作为参数使用。
        //委托TestIn<Son>的泛型与委托TestIn<Father>存在父子关系,
        //用in修饰泛型T,按照规则,作为看似委托TestIn<Son>装委托TestIn<Father>,
        //实际上执行TestIn<Son>时是将Son作为参数传入Father,还是满足里氏替换原则的。
        TestIn<Father> testInfather = (Father father) => {  };
        TestIn<Son> testInSon = testInfather;
        testInSon(new Son());//实际上调用的testInfather
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值