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

C# 泛型概念及用法详解

C# 泛型概念及用法详解

一,定义

泛型是 C# 的一种语言特性,允许在定义类、接口、方法、委托时,不指定具体的数据类型,而是用一个类型参数(Type Parameter)来代替,等到使用时再指定具体类型。这会大大简化我们的代码结构,同时让后期维护变得容易。

废话一大堆,那么泛型到底长啥样?,看到下面代码中的 “T” 没有,那就是泛型。

static void Main(string[] args) { Program program = new Program(); program.MyClassMethod(100); program.MyClassMethod2<int>(100); } public void MyClassMethod(int a) { Console.WriteLine(a); } public void MyClassMethod2<T>(T a) { Console.WriteLine(a); Console.WriteLine(a.GetType().ToString()); }

二,为什么要用泛型

重载是 “每种类型写一遍”,泛型是 “写一遍所有类型通用”;类型少的时候重载还行,类型多了泛型才是正道 —— 代码复用、维护方便、类型安全。

namespace 泛型 { class Program { static void Main(string[] args) { int result = Test.Add(3, 4); Console.WriteLine(result); Console.ReadKey(); } } public class Test { public static int Add(int x, int y) { return x + y; } public static int Add(string x, string y) { return int.Parse(x) + int.Parse(y); } } }

那么下面就用泛型的方式来封装一下这个加法运算。

注意一下写法,在 Add 后面要加上 这句,不然会报错。

public int Add<T>(T x, T y) { return 0 ; }

三、泛型和 Object 类型的区别

下面是一些介绍:

C# 中Object是一切类型的基类,可以用来表示所有类型,而泛型是指将类型参数化以达到代码复用提高软件开发工作效率的一种数据类型。一句话总结 object 是 “万能盒子”,什么都能装,但装进去就不知道是什么了,用的时候要小心;泛型是 “模板盒子”,你指定装什么它就装什么,编译器帮你盯着,不会装错。

C# 中泛型是 “通用又安全”,一份代码多种类型能用,编译器帮你检查类型,不用装箱拆箱性能还好。

**object缺点:**1.因为什么都能装,编译器不检查,写错了也不报错,运行时才崩

​ 2.值类型(int、double、结构体)装到 object 里,要复制到堆上;取出来又要复制回 栈上,频繁装箱拆箱导致性能损耗。

object优点:1. object类型可以用来引用任何类型的实例;

​ 2. object类型可以存储任何类型的值;

3.可以定义object类型的参数;

​ 4.可以把object作为返回类型。

四、泛型类

定义

整个类都是泛型的,类里的字段、方法都可以用类型参数 T。

public class MyList<T> { private List<T> _list = new List<T>(); public int Count => _list.Count; public void Add(T item) { if (item != null) _list.Add(item); } } // 使用 MyList<int> intList = new MyList<int>(); intList.Add(1); intList.Add(3); Console.WriteLine(intList.Count); // 2

你天天用的List就是泛型类。

五,泛型类的继承

// 方式1:子类也是泛型,T往下传 public class Test1<T> { } public class Test2<T> : Test1<T> { } // 方式2:子类指定父类的具体类型 public class Test1<T> { } public class Test2<T> : Test1<int> { } // 父类T固定为int

六、泛型方法

**定义:**只有方法是泛型的,类不一定是泛型的。

public class Tool { // 泛型方法:只有这个方法用T public static T GetT<T>(T a) { return a; } }

七、泛型接口

**定义:**接口也是泛型的。

public interface IFace<T> { void SayHi(T msg); }

两种实现方式

// 方式1:普通类实现,指定具体类型 public class MyClass1 : IFace<string> { public void SayHi(string msg) { Console.WriteLine(msg); } } // 方式2:泛型类实现,T继续往下传 public class MyClass2<T> : IFace<T> { public void SayHi(T msg) { Console.WriteLine(msg); } }

八、泛型约束(重点!)

什么是泛型约束?

给类型参数 T 定规矩,告诉编译器 T 必须满足什么条件,这样方法里才能放心调用 T 的成员。

六种约束

约束写法含义
值类型约束where T : structT 必须是值类型
引用类型约束where T : classT 必须是引用类型
无参构造约束where T : new()T 必须有无参构造函数
基类约束where T : 基类名T 必须是该基类或其子类
接口约束where T : 接口名T 必须实现该接口
裸类型约束where T : UT 必须是 U 或 U 的子类

九,约束顺序

基类 → 接口 → new()

基类放最前面,接口放中间,new()放最后。

多个约束示例

public class MyClass<T, K, V, W, X, Y> where T : struct // T必须是值类型 where K : class // K必须是引用类型 where V : IFace<T> // V必须实现IFace<T>接口 where W : K // W必须是K或K的子类 where X : class, new() // X必须是引用类型 + 有无参构造 where Y : MyClass2 // Y必须是MyClass2或其子类 { // ... }

十、泛型 + 反射(进阶应用)

应用场景

通用比较两个对象的所有属性值是否相同,不用写一堆 if-else。

核心思路

用反射获取对象的所有属性,逐个比较,递归处理嵌套对象。

public static bool CompareType<T>(T oneT, T twoT) { Type type1 = oneT.GetType(); Type type2 = twoT.GetType(); if (!type1.Equals(type2)) return false; PropertyInfo[] props1 = type1.GetProperties(); PropertyInfo[] props2 = type2.GetProperties(); // 遍历所有属性比较 for (int i = 0; i < props1.Length; i++) { object val1 = props1[i].GetValue(oneT, null); object val2 = props2[i].GetValue(twoT, null); if (!val1.Equals(val2)) return false; } return true; }

好处:写一个方法,所有类型的对象都能比,不用每种类型写一遍。


十一、一句话速记卡

  1. 泛型= 类型参数化,写一遍代码所有类型通用
  2. 泛型类= 整个类都是模板,List 就是
  3. 泛型方法= 只有方法是模板
  4. 泛型接口= 接口是模板,实现时指定类型
  5. 泛型委托= 委托参数是模板
  6. 泛型约束= 给 T 定规矩,struct/class/new ()/ 基类 / 接口
  7. vs Object= 泛型类型安全、不用装箱、不用强转
http://www.jsqmd.com/news/1341500/

相关文章:

  • AI写作辅助工具怎么选,网文创作者实用参考
  • 铁路雨量监测系统运行的主要做法
  • NADELLA标准RKU系列轴承定制解析 - 精彩城市
  • VisualCppRedist AIO终极指南:3分钟彻底解决Windows软件兼容性问题
  • 加拿大的海牙公证是什么流程?新手零基础办理完整流程
  • 3个关键步骤:从Dhizuku用户到开源贡献者的转变之路
  • 2026空气净化设备厂商选型指南,从4个硬维度拆解
  • 关于本地编译与烧录ESP-CLAW的问题
  • UnityExplorer终极指南:5个实战技巧实现Unity游戏运行时反射调试与内存分析
  • 2026潮流球衣定制工厂选择指南 - 精彩城市
  • 终极指南:如何高效配置SeedVC-MLX语音转换模型的5个专业技巧
  • 【汇总】影视仓接口地址,影视仓最新配置接口【2026-8】
  • 机器人猎头观察:中国机器人开始全球抢市场,企业真正缺的人已经变了
  • 无线动能开关|厂房车间办公区照明优化方案
  • 别让扁桃体“小毛病”拖成“大麻烦”——病因与对策一次说清
  • 卫生资格考试复习试卷哪个押题准?别再乱买!阿虎医考给出答案 - 精彩城市
  • KernelSU Next 内核级Root解决方案实战指南
  • Zotero Style:让文献管理从枯燥到惊艳的视觉革命
  • 10秒实现单图转3D模型:革命性Convolutional Reconstruction Model(CRM)完整解析
  • 2026 安徽工贸职业技术学院单招复读班招生简章[最新发布] - 教育为先
  • 从零搭建一个全中文 AI 智能体平台——CREAO 实战指南
  • 重庆除甲醛公司靠谱推荐:避坑假除醛找靠谱除醛机构 - 重庆在线
  • 高端网站建设kgu 如何打破同质化僵局,为企业打造真正具备商业转化力的数字资产
  • 解决Ubuntu安装Anaconda后conda命令找不到的完整指南
  • FitGirl游戏启动器终极指南:3步实现高效游戏管理一体化
  • 小批量、多品种的机加厂,排产表为什么每天都要重做?
  • 如何快速掌握Godot平台游戏开发:终极钩爪机制完整指南
  • 零基础考软考高项怎么选老师?大纲制定者领衔的5位讲师适配指南
  • 业财一体化进销存系统解决企业错账乱账困扰 - 精彩城市
  • 凌晨三点,我的 AI 智能体在无限循环中烧掉了 80% API 额度:校验失败重试的死亡螺旋