zoukankan      html  css  js  c++  java
  • 泛型协变与逆变

    https://www.cnblogs.com/springsnow/p/11652915.html#_label2

    10分钟浅谈泛型协变与逆变 - 王柏成 - 博客园 (cnblogs.com)

    C#4.0泛型的协变,逆变深入剖析 - 心出发 - 博客园 (cnblogs.com)

    协变和逆变体现在泛型接口和委托上面,也就是对泛型参数的声明,可以声明为协变,或者逆变。 如果有了参数的声明,则该泛型接口或者委托称为“变体”。

    • “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型。
    • “逆变”则是指能够使用派生程度更小的类型。逆变,逆于常规的变。

    协变和逆变,使用“out”,和“in”两个关键字。但是只能用在接口和委托上面,对泛型的类型进行声明。

    协变

    当类型参数声明为“out”时,代表它是用来返回的,只能作为结果返回,中途不能更改。

    class Class1 { void Main() { ITest<Animal> customerList1 = new Test<Animal>(); ITest<Animal> customerList2 = new Test<Bird>();//这也是能编译的,在泛型中,子类指向父类,我们称为协变 //Net4.0中已有的实现 IEnumerable<Animal> list = new List<Bird>(); } }

    /// <summary> /// 动物 /// </summary> public class Animal { public int Id { get; set; } }

    /// <summary> ////// </summary> public class Bird : Animal { public string Name { get; set; } } /// <summary> /// 接口参数 out 协变, 只能是返回结果 /// </summary> /// <typeparam name="T"></typeparam> public interface ITest<out T> { //属性只能有 get 访问器 T Attr1 { get; } T Get(); // void Show(T t);//方法中T不能作为传入参数 } /// <summary> /// 注意:类没有协变逆变 /// </summary> /// <typeparam name="T"></typeparam> public class Test<T> : ITest<T> { public T Attr1 { get { return default(T); } } public T Get() { return default(T); } public void Show(T t) { } }

    逆变

    当类型参数声明为"in"时,代表它是用来输入的,只能作为参数输入,不能被返回。

    class Class1
    {
        void Main()
        {
            ITest<Bird> customerList1 = new Test<Bird>();
            ITest<Bird> customerList2 = new Test<Animal>();//父类指向子类,我们称为逆变(强制转换)
    
            //Net4.0中已有的实现
            Action<Bird> act = new Action<Animal>((Animal i) => { });
            act(new Bird());
    
    
        }
    }
    
    /// <summary>
    /// 动物
    /// </summary>
    public class Animal
    {
        public int Id { get; set; }
    }
    
    /// <summary>
    ////// </summary>
    public class Bird : Animal
    {
        public string Name { get; set; }
    }
    
    /// <summary>
    /// 逆变
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface ITest<in T>
    {
        //T Get();//不能作为返回值
        void Show(T t);
    }
    
    public class Test<T> : ITest<T>
    {
        public T Get()
        {
            return default(T);
        }
    
        public void Show(T t)
        {
            Console.Write(typeof(T).Name);
        }
    }
  • 相关阅读:
    DIY组装机
    伯努利数学习笔记的说...
    心得分享 | 软件研发效能(1)
    开发板烧录教程
    解决Windows7/10系统连接网线后显示“未识别的网络”的问题
    雷达扫描
    经验学习
    1045 Access denied for user 'root'@'localhost' (using password:YES)
    json格式化工具
    mysql安装出现error Nr.1045
  • 原文地址:https://www.cnblogs.com/springsnow/p/15201608.html
Copyright © 2011-2022 走看看