C#-协变逆变

协变:
​ 和谐的变化,自然的变化
​ 因为里氏替换原则,父类可以装子类,所以子类变父类

​ 比如 string 变成 object,感受是和谐的

​ 逆变:
​ 逆常规的变化,不正常的变化
​ 因为里氏替换原则 父类可以装子类 但是子类不能装父类,所以父类变子类

​ 比如 object 变成 string,感受是不和谐的

​ 协变和逆变是用来修饰泛型的
​ 协变:out
​ 逆变:in
​ 用于在泛型中修饰泛型字母的,只有泛型接口和泛型委托能使用

// 作用                                                                
                                                                               
// 1.返回值 和 参数                                                                   
// 用out修饰的泛型 只能作为返回值                                                            
internal delegate T TestOut<out T>();                                          
                                                                               
// 用in修饰的泛型 只能作为参数                                                              
internal delegate void TestIn<in T>(T t);                                      
                                                                               
// 2.结合里氏替换原则理解                                                                 
internal class Father { }                                                      
                                                                               
internal class Son : Father { }                                                                                                                      
                                                                               
internal class Program                                                         
{                                                                              
    private static void Main(string[] args) {                                  
        Console.WriteLine("协变逆变");                                             
                                                                               
        // 作用(结合里氏替换原则理解)                                            
                                                                               
        // 协变 父类总是能被子类替换                                                        
        // 看起来 就是 son ——> father                                               
        TestOut<Son> os = () => new Son();                                     
                                                                               
        TestOut<Father> of = os;                                               
        Father          f  = of(); // 实际上 返回的 是os里面装的函数 返回的是Son                 
                                                                               
        // 逆变 父类总是能被子类替换                                                        
        // 看起来像是 father——>son 明明是传父类 但是你传子类 不和谐的                                
        TestIn<Father> iF = value => { };                                      
                                                                               
        TestIn<Son> iS = iF;                                                   
                                                                               
        iS(new Son()); // 实际上 调用的是 iF                                              
    }                                                                          
}                                                                              

​ 协变 out
​ 逆变 in
​ 用来修饰泛型替代符,只能修饰接口和委托中的泛型

​ 作用两点:

  1. out 修饰的泛型类型只能作为返回值类型 ,in 修饰的泛型类型只能作为参数类型
  2. 遵循里氏替换原则,用 out 和 in 修饰的泛型委托,可以相互装载(有父子关系的泛型)

​ 协变:父类泛型委托装子类泛型委托

​ 逆变:子类泛型委托装父类泛型委托

猜你喜欢

转载自blog.csdn.net/weixin_53163894/article/details/131459012