c#-泛型、协变、逆变
泛型简单介绍:
可以使用泛型声明的元素:类、接口、方法、委托
泛型之前:
泛型之前使用object封装不同类型的参数,缺点:性能差、运行时判断类型(不安全)...
泛型是在编译期间转为实际类型副本,所以性能好,还可以使用约束对泛型进行约束
泛型约束:
约束泛型类型必须满足约束。使用泛型约束后,可以像使用约束类型的方式使用泛型变量
约束种类:
where T:class//引用类型约束
where T:new()//无参构造函数约束,加了此约束后可以使用无参构造函数创建实例:T t = new T();
where T:类//具体类或其子类约束
where T:接口//具体接口或其子类约束
where T:struct//值类型约束
where T:People,new(),ISport //多个约束
协变逆变:
协变逆变只能放在接口或委托中使用
个人理解:协变逆变可以使我们的代码更灵活,帮我们做了类型转换操作。协变是子类转父类;逆变是父类转子类。
协变(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>();
}
c#-泛型、协变、逆变的更多相关文章
- 解读经典《C#高级编程》最全泛型协变逆变解读 页127-131.章4
前言 本篇继续讲解泛型.上一篇讲解了泛型类的定义细节.本篇继续讲解泛型接口. 泛型接口 使用泛型可定义接口,即在接口中定义的方法可以带泛型参数.然后由继承接口的类实现泛型方法.用法和继承泛型类基本没有 ...
- .NET Core CSharp初级篇 1-8泛型、逆变与协变
.NET Core CSharp初级篇 1-8 本节内容为泛型 为什么需要泛型 泛型是一个非常有趣的东西,他的出现对于减少代码复用率有了很大的帮助.比如说遇到两个模块的功能非常相似,只是一个是处理in ...
- Java泛型的逆变
在上篇<Java泛型的协变>这篇文章中遗留以下问题——协变不能解决将子类型添加到父类型的泛型列表中.本篇将用逆变来解决这个问题. 实验准备 我们首先增加以下方法,见代码清单1所示. 代码清 ...
- C#中泛型方法与泛型接口 C#泛型接口 List<IAll> arssr = new List<IAll>(); interface IPerson<T> c# List<接口>小技巧 泛型接口协变逆变的几个问题
http://blog.csdn.net/aladdinty/article/details/3486532 using System; using System.Collections.Generi ...
- C#的in/out关键字与协变逆变
C#提供了一组关键字in&out,在泛型接口和泛型委托中,若不使用关键字修饰类型参数T,则该类型参数是不可变的(即不允许协变/逆变转换),若使用in修饰类型参数T,保证"只将T用于输 ...
- ios开发ios9新特性关键字学习:泛型,逆变,协变,__kindof
一:如何去学习?都去学习什么? 1:学习优秀项目的设计思想,多问几个为什么,为什么要这么设计,这么设计的好处是什么,还能不能在优化 ,如何应用到自己的项目中 2:学习优秀项目的代码风格,代码的封装设计 ...
- Programming In Scala笔记-第十九章、类型参数,协变逆变,上界下界
本章主要讲Scala中的类型参数化.本章主要分成三个部分,第一部分实现一个函数式队列的数据结构,第二部分实现该结构的内部细节,最后一个部分解释其中的关键知识点.接下来的实例中将该函数式队列命名为Que ...
- java协变逆变,PECS
public static void main(String[] args) { // Object <- Fruit <- Apple <- RedApple System.out ...
- 协变 & 逆变
都跟里氏替换原则有关. 协变:你可以用一个子类对象去替换相应的一个父类对象,这是完全符合里氏替换原则的,和协(谐)的变.如:用Swan替换Bird. 逆变:你可以用一个父类对象去替换相应的一个子类对象 ...
- C#核心语法讲解-泛型(详细讲解泛型方法、泛型类、泛型接口、泛型约束,了解协变逆变)
泛型(generic)是C#语言2.0和通用语言运行时(CLR)的一个新特性.泛型为.NET框架引入了类型参数(type parameters)的概念.类型参数使得设计类和方法时,不必确定一个或多个具 ...
随机推荐
- FWT-快速沃尔什变换
FWT-快速沃尔什变换 FWT有啥用啊 我们知道,FFT可以解决多项式的卷积,即 \[ C_k=\sum_{i+j=k}A_i*B_j \] 如果将操作符换一下,换成集合运算符 比如 \[ C_k=\ ...
- 远程文件传输命令•RHEL8/CentOS8文件上传下载-用例
scp协议 scp [options] [本地用户名@IP地址:]file1 [远程用户名 @IP 地址 :] file2 options: -v 用来显示进度,可以用来查看连接,认证,或是配置错误. ...
- C# API强制关机、重启以及注销计算机
在Windows系统中有2种方式进行关机.重启以及注销计算机操作: 1.使用shutdown()命令:2.使用系统API: 以下是使用系统API进行操作的实例. 程序实例界面: 程序实例代码: 1 u ...
- Python连载28-logging设置&logger解析
一.logging模块讲解 1.函数:logging.basicConfig() 参数讲解: (1)level代表高于或者等于这个值时,那么我们才会记录这条日志 (2)filename代表日志会写在这 ...
- contentType: 'application/json' C#后台怎么处理
contentType: 'application/json' 的处理如下: $(function () { $.ajax({ 'url': "/Home/Send2SHengPi" ...
- RabbitMQ 在Windows环境下安装
1. 下载RabbitMQ和Erlang RabbitMQ下载地址 https://www.rabbitmq.com/install-windows.html RabbitMQ是用Erlang编程语 ...
- 那些前端二进制操作API
一直以来,前端的工作主要涉及的是字符串操作,而对二进制的数据接触较少.但是这种需求却一直存在着,尤其是HTML5之后,随着web应用越来越复杂,File,Blob,TypedArray这些API的出现 ...
- Prometheus 编写告警规则案例
Prometheus 编写告警规则案例 注:确保alertmanager配置完毕! 1.创建编辑文件:vim /usr/local/prometheus/rules/node.yml # groups ...
- C++ 中 string和char* 的区别
C++ 中 string和char* 的区别 1.定义: string:string是STL当中的一个容器,对其进行了封装,所以操作起来非常方便. char*:char *是一个指针,可以指向一个字符 ...
- juc包下四大并发工具
juc.CountDownLatch 闭锁 一个线程在等待一组线程后再恢复执行 await()等待其他线程执行完毕 被等待线程执行完毕后计数器-1 如何知道其他线程执行完了? 计数器,若一组线程为,C ...