可变性(variance)——协变(convariance),逆变(contravariance),不变(invariance)

应用在泛型委托,泛型接口上。

一。准备知识——赋值兼容性

      将派生类的对象赋值给基类型变量。

复制代码
    class Animal {
        public int NumerOfLegs = 4;
    }

    class Dog:Animal {
    }
class Program { static void Main(string[] args) { Animal a1 = new Animal(); Animal a2 = new Dog(); // 派生类变量赋给基类型变量————继承了基类的字段 Console.WriteLine($"Number of dog legs:{a2.NumerOfLegs}"); } }
复制代码

二。协变

     将委托参数类型的派生类型赋值给委托参数类型的基类型,以下代码编译报错——无法隐式类型转换

    出错原因:泛型委托参数类型虽然存在派生关系,但委托Factory<Dog>与Factory<Animal>间不存在派生关系,所在赋值兼容性不适用。

复制代码
class Animal {
            public int Legs = 4;
        }

        class Dog : Animal {
        }

        delegate T Factory<T>();    // 有返回值,无参数泛型委托

        class Program {
            // 匹配Factory委托的方法
            static Dog MakeDog() {
                return new Dog();
            }
            static void Main(string[] args) {
                Factory<Dog> dogMaker = MakeDog;         // 使用静态方法给委托赋值
                Factory<Animal> animalMaker = dogMaker;  // 编译报错:无法隐式类型转换
                Console.WriteLine(animalMaker().Legs.ToString());
            }
        }
复制代码

==》》正式引入协变

      将派生类型用作输出值,可以赋给基类型引用。为了让编译器知道我们的期望,必须使用out标记委托声明中的类型参数

     用下面代码替换上面委托定义行。

delegate T Factory<out T>();

三。逆变

     只作输入参数类型为基类型,可以传入派生类对象

复制代码
class Animal {
        public int NumberOfLegs = 4;
    }

    class Dog : Animal {
    }

    delegate void Action1<in T>(T a);    // 无返回值,有参数泛型委托

    class Program
    {
        // 匹配Factory委托的方法
        static void ActOnAnimal(Animal a) {
            Console.WriteLine(a.NumberOfLegs);
        }
        static void Main(string[] args) {
            Action1<Animal> act1 = ActOnAnimal; // 使用静态方法给委托赋值
            Action1<Dog> dog1 = act1;           // 基类参数委托赋给派生类参数委托
            dog1(new Dog());                    // 传入派生类对象
        }
    }
复制代码

四。协变与逆变不同

 

 五。接口的协变与逆变

 

六。关于可变的更多内容

 

七。不变

     

posted @   獨懼  阅读(121)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示