namespace Lesson17_协变逆变 { #region 知识点一 什么是协变逆变 //协变: //和谐的变化,自然的变化 //因为 里氏替换原则 父类可以装子类 //所以 子类变父类 //比如 string 变 object //感受是和谐的 //逆变: //逆常规的变化,不正常的变化 //因为 里氏替换原则 父类可以装子类 但子类不能装父类 //所以 父类变子类 //比如 object 变 string //感受是不正常的 //协变和逆变是用来修饰泛型的 //协变:out //逆变:in //用于在泛型中 修饰 泛型字母 //只有泛型接口和泛型委托能使用 #endregion #region 知识点二 作用 //1.返回值 和 参数 //用 out 修饰的泛型 只能作为返回值 不能作为参数 delegate T TestOut(); //用 in 修饰的泛型 只能作为参数 不能作为返回值 delegate void TestIn(T t); //注意:只能在泛型接口和泛型委托中使用 interface Test { void TestFun(T v); T2 TestFun2(); } //2.结合里氏替换原则理解 class Father { } class Son : Father { } #endregion internal class Program { static void Main(string[] args) { #region 知识点三 (结合里氏替换原则) //协变:子类变父类 TestOut os = () => { return new Son(); }; TestOut of = os;//不能直接装,TestOut必须通过协变的方式才能装os Father f = of();//实际返回的是Son类型的对象 //逆变:父类变子类 TestIn iF = (value) => { }; TestIn iS = iF;//不能直接装,TestIn必须通过逆变的方式才能装iF iS(new Son());//实际传递进去的是Father类型的对象 #endregion } } } //总结 //协变 out //逆变 in //用来修饰 泛型替代符的 只能修饰接口和委托中的泛型 //作用两点 //1.out修饰的泛型类型 只能作为返回值类型 in修饰的泛型类型 只能作为 参数类型 //2.遵循里氏替换原则的 用out和in修饰的 泛型委托 可以相互装载(有父子关系的泛型) // 协变 父类泛型委托装子类泛型委托 逆变 子类泛型委托装父类泛型委托