C#泛型详解及关键字作用
作者:黄厚镇 发布时间:2023-04-07 20:23:12
这篇文章主要来讲讲c#中的泛型,因为泛型在c#中有很重要的位置,对于写出高可读性,高性能的代码有着关键的作用。
一、什么是泛型?
泛型是 2.0 版 C# 语言和公共语言运行库 (CLR) 中的一个非常重要的新功能。
我们在编程程序时,经常会遇到功能非常相似的模块,只是它们处理的数据不一样。但我们没有办法,只能分别写多个方法来处理不同的数据类型。这个时候,那么问题来了,有没有一种办法,用同一个方法来处理传入不同种类型参数的办法呢?泛型的出现就是专门来解决这个问题的,可以看出,微软还是很贴心的。
二、为什么要使用泛型?
接下来我们来看一段代码。
public class GenericClass
{
public void ShowInt(int n)
{
Console.WriteLine("ShowInt print {0},ShowInt Parament Type Is {1}",n,n.GetType());
}
public void ShowDateTime(DateTime dt)
{
Console.WriteLine("ShowDateTime print {0},ShowDateTime Parament Type Is {1}", dt, dt.GetType());
}
public void ShowPeople(People people)
{
Console.WriteLine("ShowPeople print {0},ShowPeople Parament Type Is {1}", people, people.GetType());
}
}
static void Main(string[] args)
{
GenericClass generice = new GenericClass();
generice.ShowInt(11);
generice.ShowDateTime(DateTime.Now);
generice.ShowPeople(new People { Id = 11, Name = "Tom" });
Console.ReadKey();
}
显示结果:
我们可以看出这三个方法,除了传入的参数不同外,其里面实现的功能都是一样的。在1.1版的时候,还没有泛型这个概念,那么怎么办呢。就有人想到了OOP三大特性之一的继承,我们知道,C#语言中,object是所有类型的基类,将上面的代码进行以下优化:
public class GenericClass
{
public void ShowObj(object obj)
{
Console.WriteLine("ShowObj print {0},ShowObj Parament Type Is {1}", obj, obj.GetType());
}
}
static void Main(string[] args)
{
Console.WriteLine("*****************object调用*********************");
generice.ShowObj(11);
generice.ShowObj(DateTime.Now);
generice.ShowObj(new People { Id = 11, Name = "Tom" });
Console.ReadKey();
}
显示结果:
我们可以看出,目地是达到了。解决了代码的可读性,但是这样又有个不好的地方了,我们这样做实际上是一个装箱拆箱操作,会损耗性能。
终于,微软在2.0的时候发布了泛型。接下来我们用泛型方法来实现该功能。
三、泛型类型参数
在使用泛型方法之前,我们先来了解下有关于泛型的一些知识。
在泛型类型或方法定义中,类型参数是在其实例化泛型类型的一个变量时,客户端指定的特定类型的占位符。 泛型类(GenericList<T>
)无法按原样使用,因为它不是真正的类型;它更像是类型的蓝图。 若要使用GenericList<T>
,客户端代码必须通过指定尖括号内的类型参数来声明并实例化构造类型。 此特定类的类型参数可以是编译器可识别的任何类型。 可创建任意数量的构造类型实例,其中每个使用不同的类型参数,如下所示:
GenericList<float> list1 = new GenericList<float>();
GenericList<ExampleClass> list2 = new GenericList<ExampleClass>();
GenericList<ExampleStruct> list3 = new GenericList<ExampleStruct>();
在GenericList<T>
的每个实例中,类中出现的每个T
在运行时均会被替换为类型参数。 通过这种替换,我们已通过使用单个类定义创建了三个单独的类型安全的有效对象。
三、泛型约束
定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的几种类型施加限制。 如果客户端代码尝试使用约束所不允许的类型来实例化类,则会产生编译时错误。 这些限制称为约束。 通过使用where
上下文关键字指定约束。 下表列出了六种类型的约束:
where T:结构(类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型。)
class MyClass<U>
where U : struct///约束U参数必须为“值 类型”
{ }
public void MyMetod<T>(T t)
where T : struct
{
}
where T:类(类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。)
class MyClass<U>
where U : class///约束U参数必须为“引用类型”
{ }
public void MyMetod<T>(T t)
where T : class
{
}
where T:new()(类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。)
class EmployeeList<T> where T : Employee, IEmployee, System.IComparable<T>, new()
{
// ...
}
where T:<基类名>(类型参数必须是指定的基类或派生自指定的基类。)
public class Employee{}
public class GenericList<T> where T : Employee
where T:<接口名称>(类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。)
/// <summary>
/// 接口
/// </summary>
interface IMyInterface
{
}
/// <summary>
/// 定义的一个字典类型
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TVal"></typeparam>
class Dictionary<TKey, TVal>
where TKey : IComparable, IEnumerable
where TVal : IMyInterface
{
public void Add(TKey key, TVal val)
{
}
}
where T:U(为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。也就是说T和U的参数必须一样)
class List<T>
{
void Add<U>(List<U> items) where U : T {/*...*/}
}
来源:https://www.cnblogs.com/hhzblogs/p/7820005.html


猜你喜欢
- 1 配置文件的方法我们编写spring 框架的代码时候。一直遵循是这样一个规则:所有在spring中注入的bean 都建议定义成私有的域变量
- 一、需要导入的jar1.commons-collections4-4.1.jar2.poi-3.17-beta1.jar3.poi-ooxm
- C# goto 语句用于直接在一个程序中转到程序中的标签指定的位置,标签实际上由标识符加上冒号构成。语法形式如下。goto Labell;
- 引言朋友要查看一个已存在包的versionCode信息,在群里面询问,由于是已经存在的apk包,并且只需要其中的versionCode信息,
- 关于java的字符串处理我们一般使用String类和StringBuffer类那么String类和StringBuffer类的区
- 本文主要介绍了Spring Security OAuth2 实现登录互踢的示例代码,分享给大家,具体如下:背景说明一个账号只能一处登录,类似
- 前面几篇案例已经将常用的交换器(DirectExchange、TopicExchange、FanoutExchange)的用法介绍完了,现在
- 一、前沿如果你学习过其他的编程语言,你就会发现 Java 的语法很是哆嗦,可是我们为什么没有放弃 Java 这门编程语言呢?因为 JVM 是
- 1、找准入口,使用ClassPathXmlApplicationContext的构造方法加载配置文件,用于加载classPath下的配置文件
- 本文主要讲解如何通过RabbitMQ实现定时任务(延时队列)环境准备需要在MQ中进行安装插件 地址链接插件介绍地址:https://www.
- Statement 和 PreparedStatement之间的关系和区别. 关系:Prepa
- 小编为面试Java程序员的朋友们整理了2017非常热门的面试中的笔试试题,如果你是一个正在准备面试Java程序员的读者,赶快学习一下吧。1,
- 第一步:下载需要添加的jar包可以在maven库中查找下载,也可以在对应官网下载maven库网址:https://mvnrepository
- 什么是容器?在Java的GUI界面设计中,关于容器的理解,从字面意思我们就可以认为它是存放控件的地方,而这个地方依托在窗体之上,常用的容器是
- 描述:由于产品需求,要求含有EditText的界面全屏显示,最好的解决方式是使用AndroidBug5497Workaround.assis
- 1.editplus1.1 官方下载https://www.editplus.com/官方下载最新的64位2 .解压就可以使用2.1 vsc
- 项目背景最近在项目上对接前端的的时候遇到了几个问题1.经常要问前端要请求参数2.要根据请求参数写大量if...else,代码散步在 Cont
- 前言:使用 interrupt 来通知线程停止运行,而不是强制停止!普通情况停止线程public class Right
- 一,栈1,概念在我们软件应用 ,栈这种后进先出数据结构的应用是非常普遍的。比如你用浏 览器上网时不管什么浏览器都有 个"后退&qu
- 什么是局部类型?C# 2.0 引入了局部类型的概念。局部类型允许我们将一个类、结构或接口分成几个部分,分别实现在几个不同的.cs文件中。局部