news 2026/9/2 15:36:55

C# 泛型完整

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C# 泛型完整

C# 泛型完整博文

标题:【C#零基础】泛型到底是什么?通俗易懂详解泛型(泛型方法/泛型类/泛型约束)

前言

初学C#时,我们经常使用List<T>,很多人只会调用,却不理解泛型设计的意义。
本文从痛点入手,一步步讲解泛型概念、使用场景、优势以及泛型约束,适合零基础初学者阅读。

一、没有泛型之前,我们面临什么问题?

假设现在需要封装一个“容器”,用来存放数据。在泛型诞生之前,主流两种写法,都有明显缺陷。

方式1:写大量重载方法/专属类

想要支持intstring、自定义Book类,就要不断复制代码,创建Int容器String容器

publicvoidShow(intdata){Console.WriteLine(data);}publicvoidShow(stringdata){Console.WriteLine(data);}

缺点:逻辑完全一致,大量重复代码,后期维护成本极高。

方式2:使用object接收所有类型

所有类型都隐式向上转为object,一套方法兼容全部类型。

publicvoidShow(objectdata){Console.WriteLine(data);}

但是隐患非常大:

  1. 装箱拆箱:值类型(int、double)存入object会产生装箱,取出时拆箱,存在性能损耗;
  2. 类型不安全:编译时不会校验类型,运行时才可能爆出类型转换异常;
  3. 可读性差:无法直观看出容器里面存放什么类型。

泛型诞生的目标:一套逻辑复用、编译期类型安全、避免装箱拆箱性能损耗

二、什么是泛型?

泛型 = 类型参数化
定义类/方法时,先用占位符(约定名称T,代表Type)代替真实数据类型;等到调用代码的时候,再指定具体类型。

通俗理解:先预留“类型空位”,使用的时候再把真实类型填进去。

三、泛型方法(入门首选)

语法:方法名称后面添加<T>声明类型占位符

/// <summary>/// 泛型方法/// </summary>/// <typeparam name="T">类型占位符</typeparam>/// <param name="data">任意类型数据</param>publicstaticvoidShow<T>(Tdata){Console.WriteLine(data);}

调用方式:

Show<int>(100);Show<string>("Hello C#");Show<Book>(newBook());

编译器会根据传入的类型,自动生成对应专属版本代码,编译阶段就能校验类型是否合法。

四、泛型类(开发最常用,List就是泛型类)

我们自己实现一个简易通用容器:

// 泛型类,T代表存放数据的类型publicclassBox<T>{publicTValue{get;set;}}

使用示例:

// 存放intBox<int>intBox=newBox<int>();intBox.Value=99;// 存放字符串Box<string>strBox=newBox<string>();strBox.Value="泛型测试";

我们天天使用的集合List<T>就是.NET内置泛型类:

List<int>numList=newList<int>();List<string>strList=newList<string>();

对比老式ArrayList(基于object):

// 不推荐!可以随意混放数据ArrayListarr=newArrayList();arr.Add(1);arr.Add("测试");// 推荐泛型集合,编译限制只能存放intList<int>list=newList<int>();list.Add(1);// list.Add("测试"); // 直接编译报错,提前规避bug

五、泛型约束 where T:xxx(重点考点)

默认情况下T可以是任意类型。
泛型约束用来限制占位符T的范围,告诉编译器这个类型具备哪些能力,否则编译器无法直接操作T。

常用约束清单

  1. where T : class:T必须是引用类型(类)
  2. where T : struct:T必须是值类型(结构体)
  3. where T : new():T必须拥有无参公共构造函数
  4. where T : 父类名称:T必须继承该父类
  5. where T : 接口名称:T必须实现指定接口

示例:无参构造约束

// 约束:T必须有无参构造函数,才能new T()publicstaticTCreateInstance<T>()whereT:new(){returnnewT();}

六、泛型三大核心优势

  1. 类型安全:编译阶段校验类型,提前拦截类型错误,避免运行时异常;
  2. 代码复用:同一套业务逻辑,支持多种数据类型,消除大量重复代码;
  3. 高性能:值类型不会发生装箱、拆箱操作,相比object方案效率更高。

七、初学者高频误区澄清

  1. 误区:泛型是动态类型
    纠正:泛型类型在编译阶段就确定,不是运行时动态切换。
  2. 误区:T是一个真实数据类型
    纠正:T只是占位符;Box<int>Box<string>是两个完全不同的封闭类型。
  3. 误区:可以直接写T num = 0;
    纠正:编译器不知道T是什么类型,无法直接赋值,需要添加约束后才能操作。
  4. 误区:泛型等价于object
    纠正:object是统一向上转型,运行时检查;泛型编译生成专属代码,编译期检查。

八、总结

泛型本质就是把数据类型当作参数,实现类型参数化。
解决了传统object方案类型不安全、性能差,以及大量重载重复代码的痛点。

日常开发使用优先级:
泛型方法>泛型类>泛型约束
最常见落地场景:List<T>集合、通用工具类、仓储泛型封装。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 15:36:12

大型Code Review太痛苦?试试终端“分章”审查法,效率翻倍

大型 Code Review 太痛苦&#xff1f;试试在终端里“一章一章”地看完整个变更之前在参与一个中大型项目时&#xff0c;我最怕的不是写代码&#xff0c;而是每周的 Code Review 环节&#xff1a;一个 MR&#xff08;Merge Request&#xff09;动辄几十个文件、上千行改动&#…

作者头像 李华
网站建设 2026/9/2 15:35:17

基于Django的二手交易系统毕业设计:从架构设计到源码实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/2 15:30:29

基于Node.js与WebSocket构建现代IRCv3网关:从协议到React Native集成实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/2 15:29:44

【单片机毕业设计】基于 STM32 单片机的多档位定量出水控制系统设计 基于 STM32 与传感器的智能热水管控系统设计与实现(012106)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机&#xff0c;Java、小程序技术领域和毕业项目实战 ✌️…

作者头像 李华
网站建设 2026/9/2 15:21:04

C++入门--STL库

1. 标准库中的string类 1.1 string类(了解) string类的文档介绍 在使用string类时&#xff0c;必须包含#include头文件以及using namespace std; 1.2 auto和范围for auto关键字 在这里补充2个C11的小语法&#xff0c;方便我们后面的学习。 • 在早期C/C中auto的含义是&#x…

作者头像 李华