C#中的泛型

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

C#中的泛型

一、泛型的概念

定义:泛型允许我们延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程

序中使用它的时候。(也就是说泛型是可以与任何数据类型一起工作的类或方法)模块内高

内聚,模块间低耦合。

泛型的使用:当我们的类/方法不需要关注调用者传递的实体是什么(公共基类工具

类),这个时候就可以使用泛型。

注意:

集合中的项允许是 object 型的值,因此可以存放任意类型的值,无法确保存入集合中

的值都是同一类型,而导致在处理时发生异常。

泛型的特性:

-有助于最大限度地重用代码、保护类型的安全以及提高性能。

-可以创建自己的泛型接口、泛型类、泛型方法、泛型事件和泛型委托。

-可创建泛型集合类

-可对泛型进行约束以访问特定数据类型的方法

-关于泛型数据类型中使用的类型的信息可在运行时通过使用反射获取

二、可空类型

对于引用类型的变量来说,如果未对其赋值,在默认情况下是 Null 值,对于值类型的

变量,如果未赋值,整型变量的默认值为 0。

但通过 0 判断该变量是否赋值了是不太准确的。在 C# 语言中提供了一种泛型类型

(即可空类型 (System.Nullable<T>))来解决值类型的变量在未赋值的情况下允许为 Null的情况。

可空类型的定义:

1 System.Nullable<T> 变量名;

2 类型? 变量名;

可空类型常用方法:

属性或方法

作用

HasValue

若变量有值则为True,若为null则为False

Value

返回可空类型变量中存储的真正的值,当HasValue为True时才可以使用

举例如下:

1 class Program

2 {

3 static void Main(string[] args)

4 {

5 int? i = null;

6 double? d = 3.14;

7 if (i.HasValue)

8 {

9 Console.WriteLine("i 的值为{0}", i);

10 }

11 else

12 {

13 Console.WriteLine("i 的值为空!");

14 }

15 if (d.HasValue)

16 {

17 Console.WriteLine("d 的值为{0}", d);

18 }

19 else

20 {

21 Console.WriteLine("d 的值为空!");

22 }

23 }24 }

三、泛型方法

在 C# 语言中泛型方法是指通过泛型来约束方法中的参数类型,也可以理解为对数据类型设

置了参数。

如果没有泛型,每次方法中的参数类型都是固定的,不能随意更改。

在使用泛型后,方法中的数据类型则有指定的泛型来约束,即可以根据提供的泛型来传递不

同类型的参数。

泛型方法的定义:

定义泛型方法需要在方法名和参数列表之间加上<>,并在其中使用 T 来代表参数类型。

注意:

C#中泛型方法中只能使用object类具有的方法。

举例如下:

1 class Program

2 {

3 static void Main(string[] args)

4 {

5 //T设置为double类型

6 GenericFunc<double>(3.3, 4);

7 //T设置为int类型

8 GenericFunc<int>(3, 4);

9 }

10

11 //泛型方法

12 private static void GenericFunc<T>(T a, T b)

13 {

14 Console.WriteLine("参数1{0} 类型:{1},参数2{2},类型:

{3}",a,a.GetType(),b,b.GetType());

15 }

16 }

  • 泛型类

C# 语言中泛型类的定义与泛型方法类似,是在泛型类的名称后面加上<T>,当然,也可以定

义多个类型,即“<T1,T2,・・・>”。

定义形式如下:

1 class 类名<T1,T2,>

2 {

3 //类的成员

4 }

这样,在类的成员中即可使用 T1、T2 等类型来定义。

举例如下:

1 /// <summary>

2 /// 自定义泛型类

3 /// </summary>

4 /// <typeparam name="T"></typeparam>

5 class MyTest<T>

6 {

7 private T[] items = new T[3];

8 private int index = 0;

9 //向数组中添加项

10 public void Add(T t)

11 {

12 if (index < 3)

13 {

14 items[index] = t;

15 index++;

16 }

17 else

18 {

19 Console.WriteLine("数组已满!");

20 }

21 }

22 //读取数组中的全部项

23 public void Show()

24 {

25 foreach(T t in items)

26 {

27 Console.WriteLine(t);28 }

29 }

30 }

五、泛型中的数据约束

泛型中的数据约束可以指定泛型类型的范围。

若给T类型的数据约束struct,则T只能接受struct的子类类型,否则编译错误。

举例如下:

1 /// <summary>

2 /// 限定了类型的范围:只能是IShape接口的实现类

3 /// </summary>

4 /// <typeparam name="T"></typeparam>

5 class MyTest<T> where T:IShape

6 {

7 private T[] items = new T[3];

8 private int index = 0;

9 //向数组中添加项

10 public void Add(T t)

11 {

12 if (index < 3)

13 {

14 items[index] = t;

15 index++;

16 }

17 else

18 {

19 Console.WriteLine("数组已满!");

20 }

21 }

22 //读取数组中的全部项

23 public void Show()

24 {

25 foreach (T t in items)

26 {

27 Console.WriteLine(t);

28 }

29 }30 }

1 class Program

2 {

3 static void Main(string[] args)

4 {

5 MyTest<Rectangle> testObj = new MyTest<Rectangle>();

6

7 testObj.Add(new Rectangle(100,200));

8 testObj.Add(new Rectangle(50, 50));

9

10 testObj.Show();

11 }

12 }

六、泛型集合

C# 语言中泛型集合是泛型中最常见的应用,主要用于约束集合中存放的元素。

由于在集合中能存放任意类型的值,在取值时经常会遇到数据类型转换异常的情况,因此推

荐在定义集合时使用泛型集合。

泛型集合中主要使用 List<T> 和 Dictionary<K,V> 。

1、List<T>类

List<T>类是 ArrayList 类的泛型等效类。该类使用大小可按需动态增加的数组实现

IList<T> 泛型接口。

举例如下:

1 class Program

2 {

3 static void Main(string[] args)

4 {

5 //定义泛型集合

6 List<int> list = new List<int>();

7 //向集合中存入3个变量

8 list.Add(5);

9 list.Add(10);

10 list.Add(15);11 //遍历集合中的元素

12 foreach (var i in list)

13 {

14 Console.WriteLine(i);

15 }

16 }

17 }

2、Dictionary<K,V>

Dictionary<K,V>是 HashTable相对应的泛型集合,其存储数据的方式与哈希表相似,通

过键/值来保存元素,并具有泛型的全部特征,编译时检查类型约束,读取时无须类型转

换。

使用约束:

从一组键(Key)到一组值(Value)的映射,每一个添加项都是由一

个值及其相关连的键组成

任何键都必须是唯一的

键不能为空引用null,若值为引用类型,则可以为空值

Key和Value可以是任何类型(string,int,class 等)

举例如下:

1 class Program

2 {

3 static void Main(string[] args)

4 {

5 Dictionary<int, Student> dictionary = new Dictionary<int, Student>();

6 Student stu1 = new Student(1, "小明", 20);

7 Student stu2 = new Student(2, "小李", 21);

8 Student stu3 = new Student(3, "小赵", 22);

9 dictionary.Add(stu1.id, stu1);

10 dictionary.Add(stu2.id, stu2);

11 dictionary.Add(stu3.id, stu3);

12 Console.WriteLine("请输入学号:");

13 int id = int.Parse(Console.ReadLine());

14 if (dictionary.ContainsKey(id))

15 {

16 Console.WriteLine("学生信息为:{0}", dictionary[id]);17 }

18 else

19 {

20 Console.WriteLine("您查找的学号不存在!");

21 }

22 }

23 }

七、IComparable、IComparer自定义排序

在 C# 语言中提供了 IComparer 和 IComparable 接口比较集合中的对象值,主要用于对

集合中的元素排序。

IComparer 接口用于在一个单独的类中实现,用于比较任意两个对象。

IComparable 接口用于在要比较的对象的类中实现,可以比较任意两个对象。

在比较器中还提供了泛型接口的表示形式,即 IComparer<T> 和 IComparable<T> 的形

式。

1、 IComparable<T> 接口

要比较的自定义类型需要继承IComparable <T> 接口,并实现以下方法:

方法

作用

CompareTo(T obj)

比较两个对象值

返回值小于0代表当前实例小于比较实例

返回值等于0代表二者相等。

返回值大于0代表当前实例大于比较实例

如果需要对集合中的元素排序,通常使用 CompareTo 方法实现,下面通过实例来演示

CompareTo 方法的使用。

1 class Student:IComparable<Student>

2 {

3 //提供有参构造方法,为属性赋值

4 public Student(int id,string name,int age)

5 {

6 this.id = id;

7 this.name = name;

8 this.age = age;

9 }10 //学号

11 public int id { get; set; }

12 //姓名

13 public string name { get; set; }

14 //年龄

15 public int age { get; set; }

16 //重写ToString 方法

17 public override string ToString()

18 {

19 return id + "" + name + "" + age;

20 }

21 //定义比较方法,按照学生的年龄比较

22 public int CompareTo(Student other)

23 {

24 if (this.age < other.age)

25 {

26 return 1;

27 }

28 else if(this.age == other.age)

29 {

30 return 0;

31 }

32 else

33 {

34 return 1;

35 }

36 }

37 }

1 class Program

2 {

3 static void Main(string[] args)

4 {

5 //创建一个泛型列表,列表中的元素类型为Student

6 List<Student> stuList = new List<Student>();

7 //在元素中添加三个元素

8 stuList.Add(new Student(3, "张三", 20));

9 stuList.Add(new Student(1, "李四", 15));

10 stuList.Add(new Student(2, "王五", 18));

1112 //遍历并输出

13 foreach (var stu in stuList)

14 {

15 Console.WriteLine(stu);

16 }

17

18 Console.WriteLine("排序后:");

19 //排序

20 stuList.Sort();

21

22 //遍历并输出

23 foreach(var stu in stuList)

24 {

25 Console.WriteLine(stu);

26 }

27 }

28 }

2、 IComparer <T> 接口

如果要使得自定义类型可以使用泛型集合中的Sort方法进行排序,那么可自定义一个排序

类,实现IComparer <T> 接口中的以下方法:

方法

作用

Compare(T obj1,T obj2)

比较两个对象值

返回值小于0代表当前实例小于比较实例

返回值等于0代表二者相等。

返回值大于0代表当前实例大于比较实例

新建学生类型排序类StudentComparer ,实现IComparer<Student>接口。

代码如下:

1 /// <summary>

2 /// 比较类,用于两个Student对象比较

3 /// </summary>

4 class StudentComparer : IComparer<Student>

5 {

6 /// <summary>

7 /// 比较方法

8 /// </summary>

9 /// <param name="x"></param>10 /// <param name="y"></param>

11 /// <returns></returns>

12 public int Compare(Student x, Student y)

13 {

14 if(x.age < y.age)

15 {

16 return 1;

17 }

18 else if(x.age > y.age)

19 {

20 return 1;

21 }

22 else

23 {

24 return 0;

25 }

26 }

27 }

1 class Program

2 {

3 static void Main(string[] args)

4 {

5 //创建一个泛型列表,列表中的元素类型为Student

6 List<Student> stuList = new List<Student>();

7 //在元素中添加三个元素

8 stuList.Add(new Student(3, "张三", 20));

9 stuList.Add(new Student(1, "李四", 15));

10 stuList.Add(new Student(2, "王五", 18));

11

12 //遍历并输出

13 foreach (var stu in stuList)

14 {

15 Console.WriteLine(stu);

16 }

17

18 Console.WriteLine("排序后:");

19 //排序

20 stuList.Sort(new StudentComparer());

2122 //遍历并输出

23 foreach(var stu in stuList)

24 {

25 Console.WriteLine(stu);

26 }

27 }

28 }

DeepSeek V4架构深度解析:MoE、动态稀疏路由与中文长文本优化 语言的工程落地正从‘参数竞赛’转向‘架构可控性’竞争。混合专家(MoE)作为提升推理效率的关键范式,其实际价值取决于路由稳定性与显存开销的平衡;而中文长文本理解则高度依赖位置编码鲁棒性、Tokenizer字节对齐能力及KV Cache管理机制。DeepSeek V4通过分层MoE设计、双阈值动态门控、RoPE+ALiBi混合位置编码、字节对齐BPE等创新,在保持22B激活参数的同时,显著提升法律合同、政务文档、OCR古籍等典国产场景下的语义连贯性与token稳定性。这些并非理论炫技,而是面向GPU带 阅读详情

相关推荐

C#的理解

的概念 定义:允许我们延迟编写类或方法中的编程元素的数据类的规范,直到实际在程 序中使用它的时候。(也就是说是可以与任何数据类一起工作的类或方法)模块内高 内聚,模块间低耦合。 的使用:当我们的类/方法不需要关注调用者传递的实体是什么(公共基类工具 类),这个时候就可以使用。 注意: 集合中的项允许是 object 的值,因此可以存放任意类的值,无法确保存入集合中 的值都是同一类,而导致在处理时发生异常。 可空类 对于引用类的变量来说,如果未对其赋值,在默认情况下

qq_57767445的博客 2442

C#高级--详解

C#高级–详解 一、是什么? C#2.0推出的新语法,不是语法糖,而是2.0由框架升级提供的功能。 我们在编程程序时,经常会遇到功能非常相似的模块,只是它们处理的数据不一样。但我们没有办法,只能分别写多个方法来处理不同的数据类。这个时候,那么问题来了,有没有一种办法,用同一个方法来处理传入不同种类参数的办法呢?的出现就是专门来解决这个问题的。 使用是一种增强程序功能的技术,具体表现在以下几个方面: 它有助于您最大限度地重用代码、保护类的安全以及提高性能。 您可以创建集合类。

李宥的博客 1万+

C# 详解(类,方法,接口,委托,约束,反射 )

(Generic),是将不确定的类预先定义下来的一种C#高级语法,我们在使用一个类,接口或者方法前,不知道用户将来传什么类,或者我们写的类,接口或方法相同的代码可以服务不同的类,就可以定义为。这会大大简化我们的代码结构,同时让后期维护变得容易。...............

熊思雨的博客 2万+

C#入门类、集合、方法、约束、委托

集合和ArrayList的装箱拆箱、常见的类和方法、约束、 委托很难理解?不然在接触的一个新的概念的时候,总会感觉难以理解,当你掌握并能熟练地使用的时候,发现这个概念其实简单的,我相信大多数码农都会有这种似曾相识的感觉。可能大多数人刚学习的时候觉得很难理解,当然我也是这样的,所以便写下这篇文章加深一下对的印象。

dotNet全栈开发 4万+

c#: 接口、方法

可以自定义接口、类、方法、事件、委托。 1>自定义接口 和普通接口一样,一个接口通常也是与某些对象相关的约定规程。接口的声明如下: interface  [接口名] { [接口体] } 在c#中,通过尖括号“。一般来说,声明接口与声明非接口遵循相同的规则。 接口定义完成之后,就要定义此接口的子类。定义接口的子类有以下两种方法。

匆匆那年 1万+

C#

一.所解决的问题及适用情形 假设我们声明了一个叫做MyIntStack的类,它实现了把一个int类的值压入栈以及把它们弹出。 class MyIntStack { int StackPointer = 0; int[] StackArray; public void Push(int x) { //... } public int Pop() { //... } } 然后我们希望相同的功能应用于flo.

ฅ两脚喵ฅ的博客 3457

c#使用详解:特点、继承、接口、委托

:通过参数化类来实现在同一份代码上操作多种数据类。利用“参数化类”将类抽象化,从而实现灵活的复用。在.NET类库中处处都可以看到的身影,尤其是数组和集合中,的存在也大大提高了程序员的开发效率。更重要的是,C#比C++的模板使用更加安全,并且通过避免装箱和拆箱操作来达到性能提升的目的。因此,我们很有必要掌握并善用这个强大的语言特性。 C#特点: 1、如果实例

zdhlwt2008的博客 1万+

C#

一、概述一、概述是用于处理算法、数据结构的一种编程方法。的目标是采用广适用和可交互性的形式来表示算法和数据结构,以使它们能够直接用于软件构造。类、结构、接口、委托和方法可以根据它们存储和操作的数据的类来进行参数化。能在编译时提供强大的类检查,减少数据类之间的显示转换、装箱操作和运行时的类检查。类和方法同时具备可重用性、类安全和效率高等特性,这是非类和非方法无法具备的。通常用在集合和在集合上运行的方法中。主要是提高了代码的重要性。

互联网底层民工的博客 2930

C#详解

什么是的语法为什么要用的优点是什么?约束是什么,有什么作用 什么是 就是将类做参数的技术! 详细一点来说就是: 就是就是使用类参数定义的数据类或方法。 平常使用List的时候,我们就在不知不觉中已经使用了的语法 的语法有俩种. 第一种是在类名后面加上 class My<T> { ArrayList arrList = new ArrayList();// public void Add(T

qq_40629631的博客 5999

C#

文章目录方法的实例化理论与object中的数据约束 在写程序时,若需要处理的数据类不同,但算法相同时,这时候需要用到提供了编译时类安全检测机制,该机制允许程序员在编译时检测到非法的类的本质是参数化类,也就是说所操作的数据类被指定为一个参数。 类:定义一个类,这个类中某些字段的类不确定,这些类可以在类构造的时候确定下来。 c...

空空的脑袋 5064

C#中的,与java。C++中的区别

原著 :Bill Venners、Bruce Eckel  2004.2.26 原文 :http://www.artima.com/intv/generics.html  翻译 :lover_P [人物介绍]     Anders Hejlsberg , 微软著名工程师,带领他的小组设计了C#(读作:C-Sharp)程序设计语言。Hejlsberg第一次登上软件界历史舞台是在80年

nabila的专栏 3295

[C#]C#

是为所存储或使用的一个或多个类具有占位符(类形参)的类、结构、接口和方法。集合类可以将类形参用作其存储的对象类的占位符;类形参呈现为其字段的类和其方法的参数类方法可将其类形参用作其返回值的类或用作其形参之一的类。例如,创建类的实例时,指定用于替代类形参的实际类。在类形参出现的每一处位置用选定的类进行替代,这会建立一个被称为构造类的新类。将得到根据你选择的类而定制的类安全类。例如,//...

FL1768317420的博客 913

C#入门级——类、接口、方法和委托

C#入门级——类、接口、方法和委托

dlwlrma_516的博客 4419

C#进阶】C#

🎫 hello大家好啊,我是哈桑c,本文为大家介绍 C# 中的。正确地使用可以提高代码的可读性、重用性以及灵活性,可以在一定程度上提高程序的性能。错误或者过度地使用容易导致类异常、使代码变得复杂(可读性变低)以及很难确定参数真正的类等问题。除了文中提到的用法之外,还可以创建自定义的数组、事件以及和反射的结合等。

好学若饥,谦卑若愚。 2880
上一篇: C#中的接口(Interface)
下一篇: JSON使用
chenmo2001
博客等级 码龄5年 23粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值