当前位置: 首页 > news >正文

C#8.0本质论第十二章--泛型

C#8.0本质论第十二章–泛型

C#通过泛型来促进代码重用,在词义上等价于C++模板。

在泛型编程中,数据类型也是一种参数。

12.1如果C#没有泛型

为object的方法使用值类型时,“运行时”将自动对它进行装箱,获取值类型的实例时则需要显式拆箱。

12.2捕捉异常

C#的设计者采用了与C++模板相似的语法。所以C#泛型类和结构要求开发者声明泛型类型参数以及提供泛型类型实参

12.2.1使用泛型类
12.2.2定义简单泛型类
12.2.3泛型的优点

泛型促进了类型安全

编译时类型检查减少了在运行时发生InvalidCastException异常的概率

为泛型类成员使用值类型,不再造成到object的装箱转换。

C#泛型缓解了代码膨胀

性能得以提升.

内存消耗减少,由于避免了装箱,因此减少了在堆上的内存消耗。

代码可读性更好。

12.2.4类型参数命名规范

为了强调类型参数,名称应包含T前缀。

12.2.5泛型接口和结构
12.2.6定义构造函数和终结器

泛型类或结构的构造函数(和终结器)不要求类型参数。

12.2.7用default操作符指定默认值

假定有一个结构体类型Pair的构造函数,实例化时只对数的一半进行初始化,字段Second处于未初始化的状态,会造成编译错误,我们无法给Second设置初始值,因为在编写构造函数时还不知道它的类型T具体是什么。

为应对这样的局面,C#提供了default操作符。

public struct Pair<T> : IPair<T>
{public Pair(T first){First = first;Second = default;// ...}
}

12.2.8多个类型参数

类型参数的数量(或称为元数,即arity)区分了同名类,仅元数不同的泛型应放到同一个C#文件中。

方法可以通过“参数数组”获取任意数量的实参,但泛型类型不可以。每个泛型类型的元数都必须固定。

12.2.9嵌套泛型类型

避免在嵌套类型中用同名参数隐藏外层类型的类型参数。

12.3约束

为避免异常,而是生成编译时的错误,C#允许为泛型类中声明的每个类型参数提供可选的约束列表。需要使用where关键字,后跟一对“参数:要求”

12.3.1接口约束

规定某个数据类型必须实现某个接口。

12.3.2类型参数约束

有时要求将类型实参转换为特定的类型。

假如同时指定了多个约束,那么类类型约束必须第一个出现。和接口约束不同的是不允许多个类类型约束。

12.3.3非托管约束

从C#8.0开始,结构也可以是泛型的。

12.3.4非空约束

notnull即非空约束,不能和struct和class约束共用。

12.3.5struct/class约束

将类型参数限制为任何非可空值类型或任何引用类型。

12.3.6多个约束

如果有多个类型参数,每个类型参数前面都要使用where关键字。两个where子句之间并不存在逗号。

public class EntityDictionary<TKey, TValue>: System.Collections.Generic.Dictionary<TKey, TValue>where TKey : notnullwhere TValue : EntityBase
{// ...
}
12.3.7构造函数约束

并非所有对象都肯定有公共默认构造函数,所以编译器不允许为未约束的类型参数调用默认构造函数。要在其他所有约束之后添加new()。只能对默认构造函数进行约束。

12.3.8约束继承

无论泛型类型参数,还是它们的约束,都不会被派生类继承,因为泛型类型参数不是成员。

12.4泛型方法

12.4.1泛型方法类型推断

未避免多余的编码,当编译器可以逻辑推断出想要的类型参数时,调用时可以不指定类型实参。这称为方法类型推断

12.4.2指定约束

12.5协变性和逆变性

刚接触泛型类型的人经常问一个问题:为什么不能将List类型的表达式赋给List类型的变量。既然string能转换成object,string列表应该也应兼容于object列表呀?实际情况并非如此,这个赋值动作既不类型安全,也不合法。因为他们不是协变量(covariant).

“协变量”借鉴自范畴论的术语。假定两个类型X和Y具有特殊关系,即每个X类型的值都能转换成Y类型.

使用仅一个参数的泛型类型时,可以简单地说“I是协变的”,从I想I的转换称为协变转换

为什么不合法:

// ...
// Error: Cannot convert type ...
Pair<PdaItem> pair = (Pair<PdaItem>)new Pair<Contact>();
IPair<PdaItem> duple = (IPair<PdaItem>)new Pair<Contact>();
// ...
Contact contact1 = new("Princess Buttercup");
Contact contact2 = new("Inigo Montoya");
Pair<Contact> contacts = new(contact1, contact2);// This gives an error: Cannot convert type ...
// But suppose it did not
IPair<PdaItem> pdaPair = (IPair<PdaItem>) contacts;
// This is perfectly legal, but not type-safe
pdaPair.First = new Address("123 Sesame Street");

先在应该很清楚为什么字符串列表不能作为对象列表使用了。在字符串列表中不能插入整数,但在对象列表中可以。

12.5.1使用out类型参数修饰符允许协变性

从C#4开始加入了对安全协变性的支持。要指出泛型接口应该对它的某个类型参数协变,就用out修饰符来修饰改类型参数。

用out修饰IReadOnlyPair接口的类型参数,会导致编译器验证T是否真的只用作“输出”,且永远不用于形参或属性的赋值方法。

协变转换有一些重要限制:

只有泛型接口和泛型委托才能协变。泛型类和结构永远不是协变的。

提供给“来源”和“目标”泛型类型的类型实参必须是引用类型,不能是值类型。

接口或委托必须声明为支持协变,编译器必须验证协变所针对的类型参数确实只用在“输出”位置。

12.5.2使用in类型参数修饰符允许协变性

协变性的反方向称为逆变性(contravariance)。假定X和Y类型彼此相关,每个X类型的值都能转换成Y类型。如果I和I类型总是具有相反的特殊关系–也就是说I类型的每个值都能转换成I类型–就说“I对T逆变”。

12.5.3数组对不安全协变性的支持

12.6泛型的内部机制

事实上,泛型类的“类型参数”成了元数据,“运行时“在需要时会利用它们构造恰当的类。为避免装箱,对于基于值的类型参数,其泛型实现和引用类型参数的泛型实现是不同的。

用值类型作为类型参数首次构造一个泛型类型时,”运行时“会将指定的类型参数放到CIL中合适的位置,从而创建一个具体化的泛型类型。每当代码用到时,都重用已经生成的具体化的类。

对于引用类型,泛型的工作方式稍有不同。使用引用类型作为类型参数首次构造一个泛型类型时,”运行时“会在CIL代码中用object引用替换类型参数来创建一个具体的泛型类型(而不是基于所提供的类型实参)。以后,每次引用类型参数实例化一个构造好的类型,”运行时“都重用之前生成好的泛型类型的版本–即使提供的引用类型与第一次不同。

相关文章:

C#8.0本质论第十二章--泛型

C#8.0本质论第十二章–泛型 C#通过泛型来促进代码重用&#xff0c;在词义上等价于C模板。 在泛型编程中&#xff0c;数据类型也是一种参数。 12.1如果C#没有泛型 为object的方法使用值类型时&#xff0c;“运行时”将自动对它进行装箱&#xff0c;获取值类型的实例时则需要…...

Python与ArcGIS系列(七)自动化打印地图

目录 0 简述1 获取可用打印机列表2 打印地图3 导出地图至PDF4 导出地图至图像0 简述 本篇介绍如何利用arcpy实现获取可用打印机列表、打印地图、导出地图至PDF和图像。 1 获取可用打印机列表 通过arcpy提供的ListPrinterNames()函数可以生成可用的打印机列表。 import arcpy.m…...

基于STM32单片机抢答器设计

**单片机设计介绍&#xff0c; 基于STM32单片机抢答器设计-Proteus仿真 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于STM32单片机的抢答器设计可以用于教育和培训场景中的抢答游戏或考试环节。以下是一个基本的介绍设计步骤…...

冯·诺伊曼体系结构--操作系统

文章目录 1.认识冯诺依曼系统1.1约翰冯诺依曼1.2冯诺依曼结构1.3存储器的读写速度1.4对冯诺依曼结构的认识1.5冯诺依曼结构在生活中的演示 2.操作系统--“搞管理”的软件2.1概念2.2OS存在的意义2.3管理的方式2.4系统调用和库函数概念 1.认识冯诺依曼系统 1.1约翰冯诺依曼 1.2冯…...

IDEA插件开发--持久化配置信息方案

这里写自定义目录标题 配置信息持久化存储保存配置文件的方式每种方式的实现方案1.PropertiesComponent&#xff1a;2.PersistentStateComponent&#xff1a;3.Project Settings&#xff1a;4.外部文件&#xff1a; 5.数据库&#xff1a;6.加密数据&#xff1a;7,自定义配置文件…...

Vscode禁止插件自动更新

由于电脑的vscode版本不是很新。2022.10月份的版本1.7.2&#xff0c;电脑vscode的python插件装的也是2022年4月份的某个版本&#xff0c;但插件经常自动更新&#xff0c;导致python代码无法Debug,解决办法&#xff1a; 点设置&#xff0c;搜autoUpdate, 把红色框选成无...

Zookeeper篇---第六篇

系列文章目录 文章目录 系列文章目录一、请简述Zookeeper的选主流程二、为什么Zookeeper集群的数目,一般为奇数个?三、知道Zookeeper监听器的原理吗?一、请简述Zookeeper的选主流程 Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做…...

mysql数据库存储过程之游标(光标cursor)

游标是用来存储查询结果集的数据类型&#xff0c;在存储过程和函数中可以使用游标对结果集进行循环的处理。游标的使用包括游标的声明、open、fetch和close。 一、语法。 #声明游标 declare 游标名称 cursor for 查询语句; #开启游标 open 游标名称; #获取游标记录 fetch 游标…...

「帝国风暴兵」加入 The Sandbox,推出真实的全新人物化身系列和体验!

我们很高兴宣布与流行文化中最具标志性的娱乐品牌 Shepperton 设计工作室的「帝国风暴兵」达成合作伙伴关系。这一合作标志着该科幻品牌首次进入元宇宙&#xff0c;让风暴兵的粉丝们以全新的方式体验「帝国风暴兵」。 在这个体验中&#xff0c;玩家将置身于帝国风暴兵的营地&am…...

asp.net员工管理系统VS开发sqlserver数据库web结构c#编程包括出差、请假、考勤

一、源码特点 asp.net员工管理系统是一套完善的web设计管理系统&#xff08;主要包括出差、请假、考勤基础业务管理&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010 &#xff0c;数据库为sqlserver2008&a…...

C++套接字库sockpp介绍

sockpp是一个开源、简单、现代的C套接字库&#xff0c;地址为&#xff1a;https://github.com/fpagliughi/sockpp&#xff0c;最新发布版本为0.8.1&#xff0c;license为BSD-3-Clause。目前支持Linux、Windows、Mac上的IPv4、IPv6和Unix域套接字。其它*nix和POSIX系统只需很少的…...

Mac M2开发环境安装

持续更新 brew 安装 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"JAVA多版本环境 ## 终端下载安装 brew install --cask temurin8 brew install --cask temurin11 brew install --cask temurin17## vim ~/.…...

Linux各种版本安装详细步骤和root密码破解

文章目录 VMware新建虚拟机硬件设置设置虚拟网络挂载ISO文件 root密码破解 VMware新建虚拟机 硬件设置 设置虚拟网络 编辑>虚拟网络编辑器>VMnet8(NAT模式) 挂载ISO文件 加电>开启次虚拟机 第二项可以检查挂载上来的iso文件是否完整没有破坏 磁盘分区 选自定义分…...

Netty - 回顾Netty高性能原理和框架架构解析

文章目录 概述JDK 原生 NIO 程序的问题Why Netty使用场景Related ProjectsNetty 高性能设计I/O 模型【阻塞 I/O】&#xff1a;【I/O 复用模型】【基于 Buffer】 线程模型事件驱动模型Reactor 线程模型Netty的线程模型异步处理 Netty框架的架构设计功能特性模块组件Bootstrap、S…...

uni-app——項目day01

配置uni-app開發環境 uni-app快速上手 | uni-app官网 创建项目 图中四个划线就是要配置的地方. 选择vue2还是vue3看个人选择。 目录结构 但是现在新版本创建的项目已经没有components目录了&#xff0c;需要自己创建。 项目运行到微信开发者工具 使用git管理项目 node-mod…...

【Java、MongoDB】程序控制非关系数据库

步骤&#xff1a; &#xff08;1&#xff09;连接 连接字符串 &#xff08;2&#xff09;CRUD 类与接口 解析 &#xff08;3&#xff09;maven管理方法 依赖 <dependency><groupId>org.mongodb</groupId><artifactId>mongodb-driver-legacy<…...

MySQL查询时间处理相关函数与方法实践笔记

1. 实践案例 在查询mysql数据库获取数据时&#xff0c;有这样一个需求&#xff1a;按每30分钟分组获取电量数据&#xff0c;形成1天48个数据点。 方法一&#xff1a; select hour(a.CreateTime) 时点,case when MINUTE(a.CreateTime)<30 then 1 else 2 end 半小时,sum(a…...

springboot全局拦截sql异常

起因:非法用户可通过特定的输入(如输入内容超长)等操作,使后台逻辑发生错误,从而使后台sql语句暴露至前台,进而为sql攻击提供条件 处理流程:经查找com.mysql.cj.jdbc.exceptions的父类为SQLException,在全局异常处理类中增加如下配置,经测试不起作用 ExceptionHandler(SQLExce…...

AlGaN/GaN HFET 五参数模型

标题&#xff1a;A Five-Parameter Model of the AlGaN/GaN HFET 来源&#xff1a;IEEE TRANSACTIONS ON ELECTRON DEVICES&#xff08;15年&#xff09; 摘要—我们引入了AlGaN/GaN异质结场效应晶体管&#xff08;HFET&#xff09;漏极电流Id&#xff08;Vgs&#xff0c;Vds…...

矩阵的除法

B/A 如果矩阵A可逆&#xff0c;那么 证明&#xff1a; A/AB 如果矩阵A和B都可逆&#xff0c;那么 证明&#xff1a;...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

应用升级/灾备测试时使用guarantee 闪回点迅速回退

1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间&#xff0c; 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点&#xff0c;不需要开启数据库闪回。…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...