c#-泛型、协变、逆变

泛型简单介绍:

可以使用泛型声明的元素:类、接口、方法、委托

泛型之前:
泛型之前使用object封装不同类型的参数,缺点:性能差、运行时判断类型(不安全)...
泛型是在编译期间转为实际类型副本,所以性能好,还可以使用约束对泛型进行约束

泛型约束:
约束泛型类型必须满足约束。使用泛型约束后,可以像使用约束类型的方式使用泛型变量

约束种类:
where T:class//引用类型约束
where T:new()//无参构造函数约束,加了此约束后可以使用无参构造函数创建实例:T t = new T();
where T:类//具体类或其子类约束
where T:接口//具体接口或其子类约束
where T:struct//值类型约束

协变逆变:

协变逆变只能放在接口或委托中使用

个人理解:协变逆变可以使我们的代码更灵活,帮我们做了类型转换操作。协变是子类转父类;逆变是父类转子类。

协变(out):修饰返回值,泛型只能出现在成员的返回类型上,不能做传入参数

协变案例:

    public class Bird
    {
        public string ID { get; set; }
    }
    public class Sparrow : Bird
    {
        public string Name { get; set; }
    }

static void Main(string[] args)
        {
            Bird bird = new Sparrow();//正确,一只麻雀就是一只鸟
            List<Bird> birdList = null;
            //birdList = new List<Sparrow>();//报错,一群麻雀和一群鸟没有继承关系
            //只能用下面这两种方式
            birdList = new List<Sparrow>().Select(s=>(Bird)s).ToList();//方式1
            birdList = new List<Sparrow>().Cast<Bird>().ToList();//方式2
            //上面这两种方法写起来比较麻烦,所以有了协变,协变就是解决这个问题
            //为什么下面这个没有报错
            IEnumerable<Bird> iBirdList = new List<Sparrow>();
            //就是因为IEnumerable<out T>接口是支持协变的,协变使用out关键字
}

逆变与协变相反,是父类转换子类,使用in关键字。泛型类型只能出现在传入参数上

逆变案例:

    public interface ICustomerEnumerable<in T>
    { 

    }
    public class CustomerEnumerable<T> : ICustomerEnumerable<T>
   { 

   }

  static void Main(string[] args)
   {
        //in 逆变
       ICustomerEnumerable<Sparrow> sparrowList = new CustomerEnumerable<Bird>();
   }

原文地址:https://www.cnblogs.com/fanfan-90/p/11963741.html

时间: 2024-11-06 07:23:15

c#-泛型、协变、逆变的相关文章

c# 泛型协变逆变学习

最近在项目开发当中使用泛型委托Func较多,查看Func的定义就会发现Func的入参都会都会标记上in,出参都会标记上out. in 和out和泛型类型实参有关, 其中in代表逆变,out代表协变.自己协变和逆变在设计接口或者委托的时候也没有定义过, 因此就详细了解一下其用法. 一.关于协变和逆变 在c# 4.0后,泛型类型参数分为以下三种请情况 1.不变量   这带便泛型参数类型参数不能更改 2.协变量  泛型类型参数可以从一个类更改为它的某个基类.c#中使用out关键字标记协变量形式的泛型类

解读经典《C#高级编程》最全泛型协变逆变解读 页127-131.章4

前言 本篇继续讲解泛型.上一篇讲解了泛型类的定义细节.本篇继续讲解泛型接口. 泛型接口 使用泛型可定义接口,即在接口中定义的方法可以带泛型参数.然后由继承接口的类实现泛型方法.用法和继承泛型类基本没有区别. 不变.协变和逆变 在.Net4.0之前,泛型接口是不变的..Net4.0通过协变和逆变为泛型接口和泛型委托增加了重要的扩展. 注:本书总体非常好,但在协变和逆变方面,我认为是有缺陷的.我一直偏好通过读书籍来了解技术,而不是逛论坛,但协变和逆变的问题我研究了本书多次,都没搞懂而放弃了,反正平时

泛型之逆变和协变总结

泛型之逆变和协变总结 c# 泛型 逆变 协变 变的概念 协变(Foo<父类> = Foo<子类> ) 逆变(Foo<子类> = Foo<父类>) 逆变与协变的相互作用 变的概念 //父类 = 子类 string str = "string";  object obj = str;//变了  协变(Foo<父类> = Foo<子类> ) //泛型委托: public delegate T MyFuncA<T&g

Java泛型的逆变

在上篇<Java泛型的协变>这篇文章中遗留以下问题——协变不能解决将子类型添加到父类型的泛型列表中.本篇将用逆变来解决这个问题. 实验准备 我们首先增加以下方法,见代码清单1所示. 代码清单1 /** * * 描 述:Exp3使用逆变<br/> * 作 者:jiaan.gja<br/> * 历 史: (版本) 作者 时间 注释 <br/> * @param itemList */ public void doDecorate3(List<? super

ios开发ios9新特性关键字学习:泛型,逆变,协变,__kindof

一:如何去学习?都去学习什么? 1:学习优秀项目的设计思想,多问几个为什么,为什么要这么设计,这么设计的好处是什么,还能不能在优化 ,如何应用到自己的项目中 2:学习优秀项目的代码风格,代码的封装设计思想,为什么要这么设计,这么设计的好处是什么,还能不能在优化 ,如何应用到自己的项目中,每行代码都要用心去写,每一行代码都要力求使最简洁的 3:学习别人遇到问题是如何分析问题,解决问题的方法是什么 4:遇到新东西应该如何去学习:1:先研究要学习的东西作用是什么 ,有什么好处  2:如何使用:具体的语

C# 泛型的协变与逆变

那么先讲讲什么是"泛型类协变"你可以这样理解,正常的变换 好比object = String 这样的表达式一样协变主要是向上安全的变换,但是需要根据继承链条一层一层 的向上变化 而不需要进行转换因为是隐式转换,先上一层继承类的代码 不过使 用最容易的理解的,你认为是拆箱与装箱也没什么太大的出入 但是指泛型上的 [csharp] view plaincopy public class Animal // 动物 { } public class Dog : Animal // 狗 { }

EF中逆变和协变

EF中的增删改查: 实现步骤: 1.声明一个EF的上下文. bjhksjEntities dbContext = new bjhksjEntities(); 2.声明一个实体. HKSJ_USERS user = new HKSJ_USERS(); user.LoginName = "ssss"; user.Mail = "ssss"; user.PassWord = "ssss"; user.Plane = "ssss";

逆变协变

适用范围 协变逆变在接口泛型和委托泛型中而言 协变 把子类赋值给父类.OUT只能修饰输出参数. IEnumerable<Para> lp = new List<Chid>(); IMyCustomList<Para> c = new MyCustomList<Chid>(); 逆变 把父类赋值给子类.IN只能修饰输入参数. IMyCustomList<Chid> c = new MyCustomList<Para>(); 面向对象中任

C#4.0中的协变和逆变

原文地址 谈谈.Net中的协变和逆变 关于协变和逆变要从面向对象继承说起.继承关系是指子类和父类之间的关系:子类从父类继承所以子类的实例也就是父类的实例.比如说Animal是父类,Dog是从Animal继承的子类:如果一个对象的类型是Dog,那么他必然是Animal. 协变逆变正是利用继承关系 对不同参数类型或返回值类型 的委托或者泛型接口之间做转变.我承认这句话很绕,如果你也觉得绕不妨往下看看. 如果一个方法要接受Dog参数,那么另一个接受Animal参数的方法肯定也可以接受这个方法的参数,这