C#提升(一、泛型)

一、什么是泛型

泛型,即“参数化类型”

我们来看以下代码,目的很明确,就是显示参数类型,这种类似的代码或者说只有参数类型不同,但是功能相同时,我们如何让代码写的更优雅?
在这里插入图片描述
在泛型没有出现的.Net FrameWork 1.0时代,可以这样来写:

在这里插入图片描述
我们来看这样子写的,确实更优雅了许多,但是这样子写会有两个问题,至于哪两个问题,看完全文你将得到答案
在这里插入图片描述
为了代码更加优雅,在.Net FrameWork 2.0时代,出现了泛型
在这里插入图片描述

二、泛型的种类

2.1 泛型类

在这里插入图片描述

2.2 泛型接口

在这里插入图片描述

2.3 泛型方法

在这里插入图片描述

2.4 泛型委托

在这里插入图片描述

三、泛型的继承

3.1 基类和接口

在这里插入图片描述

3.2 普通类

在这里插入图片描述

3.3 泛型类

在这里插入图片描述

四、泛型的约束

4.1 定义三个类使用

在这里插入图片描述

4.2 不使用泛型

在这里插入图片描述
在这里插入图片描述
可以看到 前两个正常打印,第三个抛异常,这就是object什么都可以传,导致的一个问题:传参不安全,很明显Japanese没有相对应的属性
在这里插入图片描述

4.3 使用泛型

可以看到这里我们对 输入进行的约束必须为People或其子类
在这里插入图片描述
所以,当我们再传Japanese时,直接提示不过
在这里插入图片描述

4.4 约束的种类

  1. 引用类型约束
    (T : class), 即T必须是一个引用类型。必须放在第一个。
  2. 值类型约束
    (T : struct) 。 必须放在第一个。
  3. 无参构造函数约束
    new() , 必须放在最后一个。
  4. 转换类型约束(基类约束、接口约束)
    class Sample where T : Stream
    class Sample<T1, T2> where T1: T2 (如Sample<Stream, IDisposable>
    class Sample where T : Stream, IEnumerable, IComparable 可以多个接口,但是只能一个class.

指定的类不能是结构,密封类比如string,或者这些特殊类型:
System.Object
System.Enum
System.ValueType
System.Delegate

五、泛型的性能

5.1 测试代码

定义三个方法
分别是直接类型、Object、泛型
在这里插入图片描述
每个方法循环1亿次,判定性能
在这里插入图片描述

5.2 测试结果

在这里插入图片描述
我们可以很清楚的看出
直接类型≈泛型<Object

原因很明显
使用Object 涉及装箱和拆箱的过程
而泛型是延迟声明,使用的时候直接类型替换占位符,所以基本和直接类型性能一致

六、协变逆变

6.1 错误示范

在这里插入图片描述
在这里插入图片描述

6.2 协变

为了解决上述的问题,增加了协变的概念 ,在声明时增加out关键字,只能作为返回值使用
在这里插入图片描述
用它就可以这样写

IEnumerable<Bird> birds3 = new List<Bird>();
IEnumerable<Bird> birds4 = new List<Sparrow>();

在这里插入图片描述
委托可以这样写

Func<Bird> func = new Func<Bird>(() => null);
Func<Bird> func2 = new Func<Sparrow>(() => null);

6.3 逆变

逆变 :协变的逆过程,只能作为传参使用 关键字in
在这里插入图片描述

协变的逆过程

ICustomerIn<Sparrow> customerIn = new CustomerIn<Sparrow>();
ICustomerIn<Sparrow> customerIn2 = new CustomerIn<Bird>();

Action<Sparrow> action = new Action<Sparrow>((Sparrow i) => { });
Action<Sparrow> action2 = new Action<Bird>((Bird i) => { });

七、泛型的缓存

不同的类型在调用泛型时

  1. 每一个类型都会创建一份副本
  2. 每一个类型只会创建一次

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/30417.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android11 DNS解析流程

Android11 DNS解析 1. DNS解析概念 ​ DNS的全称是domain name system&#xff0c;即域名系统。主要目的是将域名解析为IP地址&#xff0c;域名是方便用户记忆&#xff0c;但网络传输中源目地址使用IP地址来进行标识的&#xff0c;所以Android中的网络应用程序在发起http请求…

Python(request)爬虫有多强大?

requests是Python中的一种HTTP客户端库&#xff0c;用于发送HTTP请求并获取服务器响应。使用requests库可以轻松地进行常见的HTTP操作&#xff0c;如GET、POST、PUT、DELETE等&#xff0c;支持HTTPS和HTTP连接以及摘要验证、基本认证等身份验证方式。 因此&#xff0c;Python的…

阿里云创建ALB_Ingress

阿里云参考文档 1、编写alb AlbConfig创建文档 rootbiking-pre-middleware:~/alb# cat ingress-alb.yaml apiVersion: alibabacloud.com/v1 kind: AlbConfig metadata: #alb名称name: ingress-alb spec:config:name: ingress-albaddressType: InternetzoneMappings:# 两个交换…

ESP32学习之定时器和PWM

一.定时器代码如下&#xff1a; #include <Arduino.h>hw_timer_t *timer NULL; int interruptCounter 0;// 函数名称&#xff1a;onTimer() // 函数功能&#xff1a;中断服务的功能&#xff0c;它必须是一个返回void&#xff08;空&#xff09;且没有输入参数的函数 //…

Redis 哨兵模式

哨兵模式 自动选举 Redis 主服务器&#xff08;当主服务器宕机时&#xff09; 在 Redis2.8 之前&#xff0c;采用手动配置主从机的形式&#xff08;会导致一段时间服务不可用&#xff09; Redis2.8 之后&#xff0c;Redis正是提供了 Sentinel&#xff08;哨兵&#xff09;来解…

逆向Android开发工程,抓包!抓包!学习哪里?

抓包是什么&#xff1f; 在Android逆向工程中&#xff0c;抓包是一项重要的技术&#xff0c;用于获取手机应用程序与服务器之间的通信数据。通过抓包&#xff0c;可以分析应用程序的网络请求&#xff0c;获取请求的URL、参数、响应数据等信息&#xff0c;对应用程序的行为进行…

Python编程入门基础及高级技能、Web开发、数据分析和机器学习与人工智能

文章目录 入门基础安装 Python 环境&#xff0c;选择一个 IDE&#xff0c;如 PyCharm、VSCode等。学习基本语法&#xff1a;变量、数据类型、条件语句、循环语句、函数、异常处理等。熟悉标准库&#xff1a;常用模块、内置函数等。学习基本的面向对象编程&#xff08;OOP&#…

Rust in Action笔记 第六章 内存

Option<T>类型在Rust中使用了空指针优化&#xff08;null pointer optimization&#xff09;来保证该类型在编译后的二进制文件中占用0个字节。None变量是通过一个空指针null pointer来表示&#xff1b;内存地址、指针、引用的区别&#xff0c;内存地址是指在内存中的一个…

【kubernetes】Etcd集群部署与验证

前言:二进制部署kubernetes集群在企业应用中扮演着非常重要的角色。无论是集群升级,还是证书设置有效期都非常方便,也是从事云原生相关工作从入门到精通不得不迈过的坎。通过本系列文章,你将从虚拟机准备开始,到使用二进制方式从零到一搭建起安全稳定的高可用kubernetes集…

基于OpenMV的自动驾驶智能小车模拟系统

一、项目简介 基于机器视觉模块OpenMV采集车道、红绿灯、交通标志等模拟路况信息&#xff0c;实现一辆能车道保持、红绿灯识别、交通标志识别、安全避障以及远程WiFi控制的多功能无人驾驶小车。 赛道规格&#xff1a; 1、编程所需软件&#xff1a; OpenMV&#xff1a;使用Op…

Python自动化测试框架:Pytest和Unittest的区别

pytest和unittest是Python中常用的两种测试框架&#xff0c;它们都可以用来编写和执行测试用例&#xff0c;但两者在很多方面都有所不同。本文将从不同的角度来论述这些区别&#xff0c;以帮助大家更好地理解pytest和unittest。 1. 原理 pytest是基于Python的assert语句和Pytho…

Git第二章、多人协作

一、多人协作一 目前&#xff0c;我们所完成的工作如下&#xff1a; • 基本完成 Git 的所有本地库的相关操作&#xff0c;git基本操作&#xff0c;分支理解&#xff0c;版本回退&#xff0c;冲突解决等等 • 申请码云账号&#xff0c;将远端信息clone到本地&#xff0c;以及推…

一种基于目标的可解释的自动驾驶预测和规划策略

摘要&#xff1a; 本文介绍了一种通过理性逆向规划进行目标识别和多模态轨迹预测的方法。通过将目标识别与MCTS 计划相结合&#xff0c;为自车生成优化计划。 最近炒得比较火的影子模式实际就是在通过数据收集的方式不断模拟自动驾驶系统按照人类驾驶习惯实现人之间的交互过程…

Qt 中动态加载窗口(C++)

在编程中&#xff0c;我经常会遇见要根据用户触发按钮&#xff0c;动态生成窗口的情况。在此有两种方法可以动态生成窗口&#xff1a;一&#xff1a;直接在槽函数中调用窗口类。二&#xff1a;将 **.ui 添加到资源文件&#xff0c;通过 QUiLoader 加载。 现将两种方法介绍如下…

linuxOPS系统服务_Linux下用户管理

用户概念以及基本作用 **用户&#xff1a;**指的是Linux操作系统中用于管理系统或者服务的人 一问&#xff1a;管理系统到底在管理什么&#xff1f; 答&#xff1a;Linux下一切皆文件&#xff0c;所以用户管理的是相应的文件 二问&#xff1a;如何管理文件呢&#xff1f; …

【新星计划回顾】第六篇学习计划-通过自定义函数和存储过程模拟MD5数据

&#x1f3c6;&#x1f3c6;时间过的真快&#xff0c;这是导师回顾新星计划学习的第六篇文章&#xff01; 最近这段时间非常忙&#xff0c;虽然导师首次参与新星计划活动已经在4月16日圆满结束&#xff0c;早想腾出时间来好好整理活动期间分享的知识点。 &#x1f3c6;&#x1…

Unsupervised Learning(无监督学习)

目录 Introduction Clustering&#xff08;聚类&#xff09; Dimension Reduction&#xff08;降维&#xff09; PCA&#xff08;Principle component analysis&#xff0c;主成分分析&#xff09; Word Embedding&#xff08;词嵌入&#xff09; Matrix Factorization(矩…

适合嵌入式开发的GUI(嵌入式学习)

嵌入式开发的GUI如何选择&#xff1f; 常见的嵌入式GUI开发方法轻量级GUI库优缺点 基于Web技术优缺点 Qt框架优缺点 原生开发优缺点 嵌入式系统的限制 常见的嵌入式GUI开发方法 嵌入式开发中的GUI&#xff08;图形用户界面&#xff09;是指在嵌入式系统中实现图形化的用户界面…

Linux权限管理(超详解哦)

Linux权限 引言文件访问者的分类文件类型与访问权限文件类型访问权限 文件权限值的表示方法修改权限的指令chmod修改文件权限通过角色/-/权限来修改通过三个八进制数修改 chown修改所有者chgrp修改所属组umask修改或查看文件权限掩码文件创建时的权限 目录的权限粘滞位 总结 引…

驱动模块和printk函数

目录 1. 驱动模板 1.1. 在源码工程路径下创建.c文件 1.2. 编写驱动模板 1.3. 将模板放到ubuntu上 1.4. 书写Makefile 1.5. 编译和安装 2. printk 2.1. Source Insight查找命令 2.2. printk讲解 2.2.1. 分析函数 2.2.2. 编写代码 2.3. 拓展 2.3.1. 关于printk函数测…