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

【微软技术栈】C#.NET 中的泛型

本文内容

  1. 定义和使用泛型
  2. 泛型的利与弊
  3. 类库和语言支持
  4. 嵌套类型和泛型

借助泛型,你可以根据要处理的精确数据类型定制方法、类、结构或接口。 例如,不使用允许键和值为任意类型的 Hashtable 类,而使用 Dictionary<TKey,TValue> 泛型类并指定允许的密钥和值类型。 泛型的优点包括:代码的可重用性增加,类型安全性提高。

1、定义和使用泛型

泛型是为所存储或使用的一个或多个类型具有占位符(类型形参)的类、结构、接口和方法。 泛型集合类可以将类型形参用作其存储的对象类型的占位符;类型形参呈现为其字段的类型和其方法的参数类型。 泛型方法可将其类型形参用作其返回值的类型或用作其形参之一的类型。 以下代码举例说明了一个简单的泛型类定义。

public class Generic<T>
{public T Field;
}

创建泛型类的实例时,指定用于替代类型形参的实际类型。 在类型形参出现的每一处位置用选定的类型进行替代,这会建立一个被称为构造泛型类的新泛型类。 你将得到根据你选择的类型而定制的类型安全类,如以下代码所示。

public static void Main()
{Generic<string> g = new Generic<string>();g.Field = "A string";//...Console.WriteLine("Generic.Field           = \"{0}\"", g.Field);Console.WriteLine("Generic.Field.GetType() = {0}", g.Field.GetType().FullName);
}

1.1 泛型术语

介绍 .NET 中的泛型需要用到以下术语:

  • 泛型类型定义 是用作模板的类、结构或接口声明,带有可包含或使用的类型的占位符。 例如, System.Collections.Generic.Dictionary<TKey,TValue> 类可以包含两种类型:密钥和值。 由于泛型类型定义只是一个模板,所以你无法创建作为泛型类型定义的类、结构或接口的实例。

  • 泛型类型参数(或类型参数)是泛型类型或方法定义中的占位符。 System.Collections.Generic.Dictionary<TKey,TValue> 泛型类型具有两个类型形参 TKey 和 TValue,它们分别代表密钥和值的类型。

  • 构造泛型类型(或 构造类型)是为泛型类型定义的泛型类型形参指定类型的结果。

  • 泛型类型实参 是被泛型类型形参所替代的任何类型。

  • 常见术语泛型类型包括构造类型和泛型类型定义。

  • 借助泛型类型参数的协变逆变,可以使用类型自变量的派生程度比目标构造类型更高(协变)或更低(逆变)的构造泛型类型。 协变和逆变统称为“变体” 。 

  • 约束是对泛型类型参数的限制。 例如,你可能会将一个类型形参限制为实现 System.Collections.Generic.IComparer<T> 泛型接口的类型,以确保可对该类型的实例进行排序。 此外,你还可以将类型形参限制为具有特定基类、具有无参数构造函数或作为引用类型或值类型的类型。 泛型类型的用户不能替换不满足约束条件的类型实参。

  • 泛型方法定义 是具有两个形参列表的方法:泛型类型形参列表和形参列表。 类型形参可作为返回类型或形参类型出现,如以下代码所示。

T Generic<T>(T arg)
{T temp = arg;//...return temp;
}

泛型方法可出现在泛型或非泛型类型中。 值得注意的是,方法不会仅因为它属于泛型类型或甚至因为它有类型为封闭类型泛型参数的形参而成为泛型方法。 只有当方法有属于自己的类型形参列表时才是泛型方法。 在以下代码中,只有方法 G 是泛型方法。

class A
{T G<T>(T arg){T temp = arg;//...return temp;}
}
class Generic<T>
{T M(T arg){T temp = arg;//...return temp;}
}

2、泛型的利与弊

使用泛型集合和委托有很多好处:

  • 类型安全。 泛型将类型安全的负担从你那里转移到编译器。 没有必要编写代码来测试正确的数据类型,因为它会在编译时强制执行。 降低了强制类型转换的必要性和运行时错误的可能性。

  • 代码更少且可以更轻松地重用代码。 无需从基类型继承,无需重写成员。 例如,可立即使用 LinkedList<T> 。 例如,你可以使用下列变量声明来创建字符串的链接列表:

    LinkedList<string> llist = new LinkedList<string>();
    
  • 性能更好。 泛型集合类型通常能更好地存储和操作值类型,因为无需对值类型进行装箱。

  • 泛型委托可以在无需创建多个委托类的情况下进行类型安全的回调。 例如, Predicate<T> 泛型委托允许你创建一种为特定类型实现你自己的搜索标准的方法并将你的方法与 Array 类型比如 Find、 FindLast和 FindAll方法一起使用。

  • 泛型简化动态生成的代码。 使用具有动态生成的代码的泛型时,无需生成类型。 这会增加方案数量,在这些方案中你可以使用轻量动态方法而非生成整个程序集。 

以下是泛型的一些局限:

  • 泛型类型可从多数基类中派生,如 MarshalByRefObject (约束可用于要求泛型类型形参派生自诸如 MarshalByRefObject的基类)。 不过,.NET 不支持上下文绑定的泛型类型。 泛型类型可派生自 ContextBoundObject,但尝试创建该类型实例会导致 TypeLoadException。

  • 枚举不能具有泛型类型形参。 枚举偶尔可为泛型(例如,因为它嵌套在被定义使用 Visual Basic、C# 或 C++ 的泛型类型中)。 

  • 轻量动态方法不能是泛型。

  • 在 Visual Basic、C# 和 C++ 中,包含在泛型类型中的嵌套类型不能被实例化,除非已将类型分配给所有封闭类型的类型形参。 另一种说法是:在反射中,定义使用这些语言的嵌套类型包括其所有封闭类型的类型形参。 这使封闭类型的类型形参可在嵌套类型的成员定义中使用。

    通过在动态程序集中触发代码或通过使用 Ilasm.exe (IL 汇编程序) 定义的嵌套类型不需要包括其封闭类型的类型参数;然而,如果不包括,类型参数就不会在嵌套类的范围内。

3、类库和语言支持

.NET 在以下命名空间中提供了大量泛型集合类:

  • System.Collections.Generic 命名空间包含 .NET 提供的大部分泛型集合类型(如 List<T> 和 Dictionary<TKey,TValue> 泛型类)。

  • System.Collections.ObjectModel 命名空间包含向类用户公开对象模型的其他泛型集合类型(如 ReadOnlyCollection<T> 泛型类)。

System 命名空间提供实现排序和等同性比较的泛型接口,还提供事件处理程序、转换和搜索谓词的泛型委托类型。

已将对泛型的支持添加到: System.Reflection 命名空间(以检查泛型类型和泛型方法)、 System.Reflection.Emit (以发出包含泛型类型和方法的动态程序集)和 System.CodeDom (以生成包括泛型的源图)。

公共语言运行时提供了新的操作码和前缀来支持 Microsoft 中间语言 (MSIL) 中的泛型类型,包括 Stelem、 Ldelem、 Unbox_Any、 Constrained和 Readonly。

Visual C++、C# 和 Visual Basic 都对定义和使用泛型提供完全支持。 

4、嵌套类型和泛型

嵌套在泛型类型中的类型可取决于封闭泛型类型的类型参数。 公共语言运行时将嵌套类型看作泛型,即使它们不具有自己的泛型类型形参。 创建嵌套类型的实例时,必须指定所有封闭泛型类型的类型实参。

相关文章:

【微软技术栈】C#.NET 中的泛型

本文内容 定义和使用泛型泛型的利与弊类库和语言支持嵌套类型和泛型 借助泛型&#xff0c;你可以根据要处理的精确数据类型定制方法、类、结构或接口。 例如&#xff0c;不使用允许键和值为任意类型的 Hashtable 类&#xff0c;而使用 Dictionary<TKey,TValue> 泛型类并…...

【毕业论文】基于微信小程序的植物分类实践教学系统的设计与实现

基于微信小程序的植物分类实践教学系统的设计与实现https://download.csdn.net/download/No_Name_Cao_Ni_Mei/88519758 基于微信小程序的植物分类实践教学系统的设计与实现 Design and Implementation of Plant Classification Practical Teaching System based on WeChat Mini…...

[量化投资-学习笔记011]Python+TDengine从零开始搭建量化分析平台-MACD金死叉策略回测

在上一章节 MACD金死叉中结束了如何根据 MACD 金死叉计算交易信号。 目录 脚本说明文档&#xff08;DevChat 生成&#xff09;MACD 分析脚本安装依赖库参数配置查询与解析数据计算 MACD 指标判断金叉和死叉计算收益绘制图形运行脚本 本次将根据交易信号&#xff0c;模拟交易。更…...

tensorboard报错解决:No dashboards are active for the current data set

版本&#xff1a;tensorboard 2.10.0 问题&#xff1a;文件夹下明明有events文件&#xff0c;但用tensorboard命令却无法显示。 例如&#xff1a; 原因&#xff1a;有可能是文件路径太长了&#xff0c;导致系统无法读取文件。在win系统中规定&#xff0c;目录的绝对路径不得超…...

线性代数本质系列(一)向量,线性组合,线性相关,矩阵

本系列文章将从下面不同角度解析线性代数的本质&#xff0c;本文是本系列第一篇 向量究竟是什么&#xff1f; 向量的线性组合&#xff0c;基与线性相关 矩阵与线性相关 矩阵乘法与线性变换 三维空间中的线性变换 行列式 逆矩阵&#xff0c;列空间&#xff0c;秩与零空间 克莱姆…...

python语法之注释

注释可用于解释Python代码。 注释可用于使代码更易读。 注释可用于在测试代码时阻止执行。 &#xff08;1&#xff09;创建注释 注释以&#xff03;开头&#xff0c;Python会忽略它们&#xff1a; #This is a comment print("Hello, World!") 注释可以放在一行…...

React【异步逻辑createAsyncThunk(一)、createAsyncThunk(二)、性能优化、createSelector】(十二)

文章目录 异步逻辑 createAsyncThunk&#xff08;一&#xff09; createAsyncThunk&#xff08;二&#xff09; 性能优化 createSelector 异步逻辑 //Product.js const onAdd () > {const name nameRef.current.value// 触发添加商品的事件dispatch(addProduct({name…...

Halcon WPF 开发学习笔记(3):WPF+Halcon初步开发

文章目录 前言在MainWindow.xaml里面导入Halcon命名空间WPF简单调用Halcon创建矩形简单调用导出脚本函数 正确显示匹配效果 前言 本章会简单讲解如何调用Halcon组件和接口&#xff0c;因为我们是进行混合开发模式。即核心脚本在平台调试&#xff0c;辅助脚本C#直接调用。 在M…...

P6入门:项目初始化9-项目详情之资源 Resource

前言 使用项目详细信息查看和编辑有关所选项目的详细信息&#xff0c;在项目创建完成后&#xff0c;初始化项目是一项非常重要的工作&#xff0c;涉及需要设置的内容包括项目名&#xff0c;ID,责任人&#xff0c;日历&#xff0c;预算&#xff0c;资金&#xff0c;分类码等等&…...

Python高级语法----使用Python进行模式匹配与元组解包

文章目录 1. 模式匹配的新特性2. 高级元组解包技巧3. 数据类的匹配与应用1. 模式匹配的新特性 Python自3.10版本起引入了结构化模式匹配的新特性,这是一种强大的工具,允许开发者用更清晰、更直观的方式处理数据结构。模式匹配类似于其他编程语言中的switch-case语句,但它更…...

MySQL安装配置与使用教程(2023.11.13 MySQL8.0.35)

CONTENTS 1. MySQL的安装与配置2. MySQL常用操作教程 1. MySQL的安装与配置 MySQL Windows Installer 下载地址&#xff1a;MySQL Installer。 我们下载最新版本&#xff08;目前是8.0.35&#xff09;的安装包&#xff0c;注意要选择更大的那个&#xff0c;名字为 mysql-inst…...

【阿里云数据采集】采集标准Docker容器日志:部署阿里云Logtail容器以及创建Logtail配置,用于采集标准Docker容器日志

文章目录 引言I 预备知识1.1 Logtail1.2 安装Logtail1.3 创建用户自定义标识机器组1.4 设置logtail容器组件重启策略II 采集服务器日志2.1 采集同一账号下同地域服务器的日志2.2 不同账号下同地域服务器的日志2.3 创建Logtail配置III 查询语法3.1 具体查询语法3.2 查询示例3.3 …...

Django中如何创建表关系,请求生命周期流程图

Django中ORM创建表关系 如何创建表关系(一对一 &#xff0c; 一对多 &#xff0c; 多对多) 图书表&#xff0c;出版社表&#xff0c;作者表&#xff0c;作者详情表 换位思考法判断表关系 图书表和出版社表 >>> 一对多 >>> 图书表是多&#xff0c;出…...

MongoDB副本集配置和创建

副本集有三类角色&#xff1a;master(primary)&#xff0c;slave(secondary)&#xff0c;仲裁服务器。 primary是主&#xff0c;只有primary能写入&#xff0c;secondary无法插入数据&#xff0c;且需要声明是slave才能查看数据 一般生产搞三个服务器做一个master和两个slave&a…...

使用 `open-uri.with_proxy` 方法打开网页

Ruby 爬虫程序如下&#xff1a; require open-uri require nokogiri# 定义代理信息 proxy_host jshk.com.cn# 定义要爬取的网页 URL url http://www.example.com# 使用代理信息打开网页 open-uri.with_proxy(proxy_host, proxy_port) do |proxy|# 使用 Nokogiri 库解析网页内…...

数据库表的设计——范式

目录 1. 设计数据表需要注意的点 2. 范式 2.1 范式简介 2.2 范式有哪些&#xff1f; 2.3 第一范式(1NF) 2.4 第二范式(2NF) 2.5 第三范式(3NF) 2.6 小结 1. 设计数据表需要注意的点 &#xff08;1&#xff09;首先要考虑设计这张表的用途&#xff0c;这张表都要存放什…...

Brute Force

Brute Force "Brute Force"&#xff08;暴力破解&#xff09;指的是一种通过尝试所有可能的组合来获取访问、解密或破解信息的攻击方法。这种攻击方法通常是基于暴力和不断尝试的&#xff0c;不依赖漏洞或弱点。通常用于破解密码、破坏系统或获取未经授权的访问权限…...

HTML简单介绍

且视他人之疑目如盏盏鬼火&#xff0c;大胆地去你的夜路。 目录 1.网页 2.Web标准 3.HTML 3.1HTML结构 3.2HTML标签​编辑 4.标签介绍 4.1排版标签 4.2文本格式化标签 4.3媒体标签 4.3.1图片标签 4.3.2 音频标签 4.3.3视频标签 5.相对路径 6.链接标签 6.1target属…...

【Java笔试强训】Day10(CM62 井字棋、HJ87 密码强度等级)

CM62 井字棋 链接&#xff1a;井字棋 题目&#xff1a; 给定一个二维数组board&#xff0c;代表棋盘&#xff0c;其中元素为1的代表是当前玩家的棋子&#xff0c;0表示没有棋子&#xff0c;-1代表是对方玩家的棋子。当一方棋子在横竖斜方向上有连成排的及获胜&#xff08;及…...

C语言求数组中出现次数最多的元素

一、前言 遇到一个需求&#xff0c;需要求数组中出现次数最多的元素&#xff0c;查找了一些资料&#xff0c;结合自己的思路&#xff0c;编写了程序并验证。 只考虑元素为非负整数的数组&#xff0c;如果有出现次数相同的元素&#xff0c;则返回较小元素。 二、编程思路 以数…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...