泛型(一)--泛型的作用和定义

article/2025/6/20 8:44:34

一、泛型的作用
泛型是.net中十分常见的一种特性。它是在.net 2.0的时候加入。那为什么要在.net 2.0的时候加入泛型这个特性呢?我们首先来看一段代码。

using System;namespace 泛型{class Program{static void Main(string[] args){int iParameter = 1;string sParameter = "hello world";DateTime dtParameter = DateTime.Now;Console.WriteLine("***************************最开始的写法*********************************");CommonMethod.ShowInt(iParameter);CommonMethod.ShowString(sParameter);CommonMethod.ShowDateTime(dtParameter);Console.ReadLine();}}}
using System;using System.Collections.Generic;using System.Text;namespace 泛型{public class CommonMethod{public static void ShowInt(int iParameter){Console.WriteLine(string.Format("这个方法是:{0},它的参数是{1},参数的类型是{2}", typeof(CommonMethod), iParameter.ToString(), iParameter.GetType().ToString()));}public static void ShowString(string sParameter){Console.WriteLine(string.Format("这个方法是:{0},它的参数是{1},参数的类型是{2}", typeof(CommonMethod), sParameter.ToString(), sParameter.GetType().ToString()));}public static void ShowDateTime(DateTime dtParameter){Console.WriteLine(string.Format("这个方法是:{0},它的参数是{1},参数的类型是{2}",typeof(CommonMethod), dtParameter.ToString(), dtParameter.GetType().ToString()));}}}

通过代码可以理解,我们只是要根据不同的类型,输出相同的内容。因为.net 1.0的时候没有泛型的概念,那么我们最简单的做法就是有多少类型,我们就写多少个方法,进行输出。

这样就会造成一些问题:

1、代码量大。.net有那么多类型,每一个类型都写一个方法,那么代码势必会很长。

2、不利于代码维护。当需要对输出内容进行修改时,则每一个方法都需要进行修改。这就是一种灾难。

那么有没有方法解决这些问题呢?

在.net 1.0的时候,我们可以通过这种方式进行解决。先上代码:

using System;namespace 泛型{class Program{static void Main(string[] args){int iParameter = 1;string sParameter = "hello world";DateTime dtParameter = DateTime.Now;Object oParameter = "Object";Console.WriteLine("***************************.net 1.0 最开始的写法*********************************");CommonMethod.ShowInt(iParameter);CommonMethod.ShowString(sParameter);CommonMethod.ShowDateTime(dtParameter);Console.WriteLine("***************************.net 1.0 优化的写法*********************************");CommonMethod.ShowObject(iParameter);CommonMethod.ShowObject(sParameter);CommonMethod.ShowObject(dtParameter);CommonMethod.ShowObject(oParameter);Console.ReadLine();}}}
using System;using System.Collections.Generic;using System.Text;namespace 泛型{public class CommonMethod{public static void ShowInt(int iParameter){Console.WriteLine(string.Format("这个方法是:{0},它的参数是{1},参数的类型是{2}", typeof(CommonMethod), iParameter.ToString(), iParameter.GetType().ToString()));}public static void ShowString(string sParameter){Console.WriteLine(string.Format("这个方法是:{0},它的参数是{1},参数的类型是{2}", typeof(CommonMethod), sParameter.ToString(), sParameter.GetType().ToString()));}public static void ShowDateTime(DateTime dtParameter){Console.WriteLine(string.Format("这个方法是:{0},它的参数是{1},参数的类型是{2}",typeof(CommonMethod), dtParameter.ToString(), dtParameter.GetType().ToString()));}public static void ShowObject(Object oParameter){Console.WriteLine(string.Format("这个方法是:{0},它的参数是{1},参数的类型是{2}",typeof(CommonMethod), oParameter.ToString(), oParameter.GetType().ToString()));}}}

代码中添加了ShowObject方法,参数传递Object类型,然后所有的类型都调用这个方法。那么结果呢?

在这里插入图片描述

运行结果是正常的。那么为什么可以这样?

1、任何父类出现的地方都可以用子类代替。

2、Object是一切类型的父类

感觉可以使用这个方法解决之前不同类型,输出相同内容的问题了。为什么后来又出现了泛型呢?

因为使用Object的方法,有两个问题:

1、装箱和拆箱的性能损耗。object是引用类型,当传递值类型时,需要转换成引用类型。

传入一个Int值(栈)需要把值从栈Copy堆里面

2、类型安全问题。当你需要传递一个int类型时,你传递了一个String类型。编译是能通过的,只有等到运行时才会报错。这是不安全的。

总结起来在.net 1.0的时代,主要有几个问题:

1、代码重复比较严重。不同的类型需要写不同的方法,造成代码冗余严重。

2、使用Object参数的形式能解决代码冗余的问题,但是性能上付出了代价。

3、使用Object参数的形式,参数类型是不安全的。任何类型的参数都能传递到方法里。

所以,为了解决这些问题,在.net 2.0的时候就引入了泛型这个特性。

还是一样,先上代码:

using System;namespace 泛型{class Program{static void Main(string[] args){int iParameter = 1;string sParameter = "hello world";DateTime dtParameter = DateTime.Now;Object oParameter = "Object";Console.WriteLine("***************************.net 1.0 最开始的写法*********************************");CommonMethod.ShowInt(iParameter);CommonMethod.ShowString(sParameter);CommonMethod.ShowDateTime(dtParameter);Console.WriteLine("***************************.net 1.0 优化的写法*********************************");CommonMethod.ShowObject(iParameter);CommonMethod.ShowObject(sParameter);CommonMethod.ShowObject(dtParameter);CommonMethod.ShowObject(oParameter);Console.WriteLine("***************************.net 泛型*********************************");CommonMethod.Show<int>(iParameter);CommonMethod.Show<string>(sParameter);CommonMethod.Show<DateTime>(dtParameter);CommonMethod.Show<Object>(oParameter);Console.ReadLine();}}}
using System;using System.Collections.Generic;using System.Text;namespace 泛型{public class CommonMethod{public static void ShowInt(int iParameter){Console.WriteLine(string.Format("这个方法是:{0},它的参数是{1},参数的类型是{2}", typeof(CommonMethod), iParameter.ToString(), iParameter.GetType().ToString()));}public static void ShowString(string sParameter){Console.WriteLine(string.Format("这个方法是:{0},它的参数是{1},参数的类型是{2}", typeof(CommonMethod), sParameter.ToString(), sParameter.GetType().ToString()));}public static void ShowDateTime(DateTime dtParameter){Console.WriteLine(string.Format("这个方法是:{0},它的参数是{1},参数的类型是{2}", typeof(CommonMethod), dtParameter.ToString(), dtParameter.GetType().ToString()));}public static void ShowObject(Object oParameter){Console.WriteLine(string.Format("这个方法是:{0},它的参数是{1},参数的类型是{2}", typeof(CommonMethod), oParameter.ToString(), oParameter.GetType().ToString()));}public static void Show<T>(T tParameter){Console.WriteLine(string.Format("这个方法是:{0},它的参数是{1},参数的类型是{2}", typeof(CommonMethod), tParameter.ToString(), tParameter.GetType().ToString()));}}}

注意里面Show的方法,这个就是泛型方法的定义。那么运行结果呢?请看图:

在这里插入图片描述

可以看到是没有问题的。

泛型的作用是什么?我用一句话概括就是不同类型的参数进行相同的操作时,你就可以考虑使用泛型。

二、泛型的定义

 public static void Show<T>(T tParameter){Console.WriteLine(string.Format("这个方法是:{0},它的参数是{1},参数的类型是{2}", typeof(CommonMethod), tParameter.ToString(), tParameter.GetType().ToString()));}

泛型方法与一般方法的区别在方法名后有一对<>。其中T表示的是一个占位符,意思是我这里会指定一个类型,但是我现在不知道,我把位置给占着。等要使用到这个方法时,我在指定类型。其采用的思想延迟思想。

其中占位符可以是一个,也可以是多个。比如Show<T,N,M,Two>都行。但是请注意,这里的占位符不能是关键词。比如class,static等。

三、泛型有没有解决问题?

第一个问题,代码冗余,这个比较明显,在main方法里面都调用了一个方法,代码简洁不少。

第二个性能问题,那我们就写一个测试代码。

首先添加一个类Monitor。代码如下:

using System;using System.Collections.Generic;using System.Diagnostics;using System.Text;namespace 泛型{public class Monitor{public static void Show(){Console.WriteLine("****************Monitor******************");{int iValue = 12345;long commonSecond = 0;long objectSecond = 0;long genericSecond = 0;{Stopwatch watch = new Stopwatch();watch.Start();for (int i = 0; i < 100000000; i++){ShowInt(iValue);}watch.Stop();commonSecond = watch.ElapsedMilliseconds;}{Stopwatch watch = new Stopwatch();watch.Start();for (int i = 0; i < 100000000; i++){ShowObject(iValue);}watch.Stop();objectSecond = watch.ElapsedMilliseconds;}{Stopwatch watch = new Stopwatch();watch.Start();for (int i = 0; i < 100000000; i++){Show<int>(iValue);}watch.Stop();genericSecond = watch.ElapsedMilliseconds;}Console.WriteLine("一般方法耗时={0}毫秒,Object方法耗时={1}毫秒,泛型方法耗时={2}毫秒" , commonSecond, objectSecond, genericSecond);}}#region PrivateMethodprivate static void ShowInt(int iParameter){//do nothing}private static void ShowObject(object oParameter){//do nothing}private static void Show<T>(T tParameter){//do nothing}#endregion}}

main方法:

using System;namespace 泛型{class Program{static void Main(string[] args){for (int i = 0; i < 5; i++){Monitor.Show();}Console.ReadLine();}}}

Monitor类中定义了ShowInt,ShowObject,Show三类方法,每个方法内都是空的,没有做任何操作。然后在Show方法中,调用ShowInt,ShowObject,Show各100000000次,通过Stopwatch计时器计算每个方法执行10000000次所需要的时间(毫秒)。

Main方法中,为了比较全面的看到时间,我这里调用了5次Show方法。结果如图:
在这里插入图片描述

明显的能看出,Object方法耗时最长,一般方法的耗时和泛型的耗时基本相差无几。

所以在性能上的问题,我们也能得到了解决。

第三个问题:类型安全问题。

当我们使用泛型方法时,在调用的适合就需要指定类型。

int iValue = 12345;

string sValue=”Hello World”;

Show(iValue)

这样是可以成功的,但是如果我们写成这样:

Show(sValue)

则编译不通过,从一定程度上解决了类型安全的问题。

四、泛型缓存

为什么泛型的效率这么高呢?这里面涉及到泛型缓存的概念。

类中的静态类型无论实例化多少次,在内存中只会有一个。静态构造函数只会执行一次。在泛型类中,T类型不同,每个不同的T类型,都会产生一个不同的副本,所以会产生不同的静态属性、不同的静态构造函数。简单的说就是不同类型的T会生成相同的副本,而相同类型的T会只用同一个副本。

请看下面的例子:

GenericCache类:

using System;using System.Collections.Generic;using System.Text;namespace 泛型{public class GenericCache<T>{static GenericCache(){Console.WriteLine("这是 GenericCache 静态构造函数");_TypeTime = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff"));}private static string _TypeTime = "";public static string GetCache(){return _TypeTime;}}}

GenericCacheTest类:

using System;using System.Collections.Generic;using System.Text;using System.Threading;namespace 泛型{public class GenericCacheTest{public static void Show(){for (int i = 0; i < 5; i++){Console.WriteLine("这是第{0}次执行......", (i + 1).ToString());Console.WriteLine(GenericCache<int>.GetCache());Thread.Sleep(100);Console.WriteLine(GenericCache<long>.GetCache());Thread.Sleep(100);Console.WriteLine(GenericCache<DateTime>.GetCache());Thread.Sleep(100);Console.WriteLine(GenericCache<string>.GetCache());Thread.Sleep(100);Console.WriteLine(GenericCache<GenericCacheTest>.GetCache());Thread.Sleep(100);}}}}

main方法:

using System;namespace 泛型{class Program{static void Main(string[] args){GenericCacheTest.Show();Console.ReadLine();}}}

运行后结果为:

在这里插入图片描述

观察结果可以看到,5次执行相同类型的时间都是一致的。并且从第二次开始,执行时并没有进入构造函数。利用泛型的这一个特性,可以实现缓存。

注意:只能为不同的类型缓存一次。泛型缓存比字典缓存效率高。泛型缓存不能主动释放


http://chatgpt.dhexx.cn/article/s8FdRgj0.shtml

相关文章

什么叫泛型?有什么作用?

作者&#xff1a;Java3y 链接&#xff1a;https://www.zhihu.com/question/272185241/answer/366129174 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 一、什么是泛型&#xff1f; Java泛型设计原则&#xff1a;…

Java泛型的作用及优点有哪些

Java泛型是J2 SE1.5中引入的一个新特性,其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 作用 第一是泛化。可以用T代表任意类型Java语言中引入泛型是一个较大的功能增强不…

第十章 泛型

10.1 泛型的理解和好处 10.1.1使用传统方法的问题分析 1&#xff09;不能加入到集合ArrayList中的数据类型进行约束(不安全) 2&#xff09;遍历的时候&#xff0c;需要进行类型转换&#xff0c;如果集合中的数据量较大&#xff0c;对效率有影响 10.1.2泛型的好处 1)编译时…

简述泛型的基本使用和作用

前言 在上一篇文章中&#xff0c;给大家讲解了泛型的概念、作用、使用场景&#xff0c;以及泛型集合、泛型接口和泛型类的用法&#xff0c;但受限于篇幅&#xff0c;并没有把泛型的内容讲解完毕。所以今天我们会继续学习泛型方法、泛型擦除&#xff0c;以及通配符等的内容&…

军职在线大学计算机基础(自主模式),《军职在线》中国哲学经典著作导读(自主模式)...

《军职在线》中国哲学经典着作导读(自主模式) 1《周易》导读 测试题C A C B D C D B B D D A B C D C D B A B 2《道德经》导读 测试题D C D C C C D A D C D B C C C A B A A B 3《庄子》导读 测试题D C D A A C B A A C A A C A D C B 4《论语》导读 测试题B B C ED B A A A …

台湾国立大学(林轩田)《机器学习技法》(第7讲)blending and bagging

课程地址&#xff1a;https://class.coursera.org/ntumlone-001/class 课件讲义&#xff1a;http://download.csdn.net/download/malele4th/10212756 注明&#xff1a;文中图片来自《机器学习技法》课程和部分博客 建议&#xff1a;建议读者学习林轩田老师原课程&#xff0c…

大学有新民之道,则大学生者负新民工作之实际责任者也。

梅贻琦&#xff0c;&#xff08;1889-1962&#xff09;&#xff0c;字月涵&#xff0c;为梅曾臣长子。自1914年由美国吴士脱大学学成归国&#xff0c;即到清华担任教学和教务长等多种职务。1931年&#xff0c;梅贻琦出任清华校长&#xff0c;自此后一直到他在台湾去世&#xff…

【转载】中庸与技术书

2019独角兽企业重金招聘Python工程师标准>>> 转自&#xff1a;图灵社区 原文作者&#xff1a;刘祺 原文地址&#xff1a;http://www.ituring.com.cn/article/213657 本次转载已经过原作者同意&#xff0c;二次转载请自行联系原作者 #中庸与技术书 在我写这篇文章之前…

《大学》《中庸》全文及翻译 (转载)

《大学》全文及翻译 原文&#xff1a; 大学之道&#xff0c;在明明德&#xff0c;在亲民&#xff0c;在止于至善。知止而后有定&#xff0c;定而后能静&#xff0c;静而后能安&#xff0c;安而后能虑&#xff0c;虑而后能得。物有本末&#xff0c;事有终始&#xff0c;知所先后…

[C语言]求一个数是否是2的n次方

设a8&#xff0c;a的二进制数为1000&#xff0c;若为16&#xff0c;则是 0001 0000&#xff0c;2的n次方转为二进制则只保留一个 1 &#xff0c; 其余位置全是0&#xff0c;因此只要判断这个数的二进制是否只有一个 1 &#xff0c;则知道这个数是否是2的n次方。 //求一个数是…

C语言|s1-s0|<=10的-6次方

#include <stdio.h> #include <math.h> double fun(double x) { double s11.0,s00.0; double t1.0; int n1; do { s0s1;//此时s0为s1的上一项 tt*(0.5-n1)*x/n; s1s1t; n; } while(fabs(s1-s0)>1e…

c语言字母能乘10吗,c语言编程中表示a乘以10的n次幂怎么表示

可以参考下面的代码&#xff1a; #include int main() { float a,s,n; sa*mi(10,n); return 0; } float mi(float x,int y) { float a; int i; a1; if(y>0) { for(i1;i<y;i) { aa*x; } } else { for(i-1;i>y;i--) { aa/x; } } return a; } 扩展资料&#xff1a; C语言…

c语言学习-编写函数求x的n次方的值

编写函数求x的n次方的值 程序流程图&#xff1a; 代码&#xff1a; #include<stdio.h> long mul(int j ,int k) { int i; long mu1; for(i0;i<k;i) mumu*j; return mu; } void main() { int x,n; long m; printf("please enter x\tn\t"); scanf("%…

c语言x的n次方怎么写_C语言入门教程(三)进制与操作符

Hello,小伙伴们大家好,今天开始进入C语言第三课时的学习。进入今天正式内容之前呢,先来看一下上次课程中的留下的一道练习题。 练习: 1.编写程序计算半径为任意浮点数的圆周长并把结果打印在屏幕上 1、进制 一个字节分成八段,每段只能记录一个0或者1要想把一个数字记录在一…

c语言n次方怎么输入_C语言中10个经典的算法,学会它,利用它

C语言中有有许多经典的算法,这些算法都是许多人的智慧结晶,也是编程中常用的算法,这里面包含了众多算法思想,掌握这些算法,对于学习更高级的、更难的算法都会有很大的帮助,会为自己的算法学习打下坚实的基础。 接下来我们先来看10道: (1) 输出9*9乘法口诀 运行结果: (2…

c语言编程如何进行n次方运算,c语言n次方怎么输入?_后端开发

python编程如何求2000到2500闰年&#xff1f;_后端开发 python编程求2000到2500闰年的方法&#xff1a;首先定义年份【i2000】&#xff1b;然后用while循环判断是否在2500内&#xff1b;接着若年份可被40整除且不被100整除&#xff0c;则是闰年&#xff0c;若年份可被400整除&a…

C语言怎么编辑次方,c语言怎么表示一个数的n次方

2009-01-05 C语言问题从键盘输入8个数,用选择法按由大到小的循序排列并输出,要求用指针来实现。 你应该自己实现这个小程序。 例子,单向链表排序(冒泡): struct student {int num; struct student *next; } struct student *paixu(struct student *head) {struct student *p,…

c语言中e的n次方怎么打,C语言中N次方怎么打

满意答案 lawq0364t 2020.05.11 采纳率&#xff1a;52% 等级&#xff1a;7 已帮助&#xff1a;2761人 有两个函数可以实现&#xff0c;double pow(double x, double y)&#xff0c;double pow10(int p) 下面是这两个函数的使用方法&#xff0c;个人建议用&#xff1a;pow10(…

c语言10的10万次方,在c语言编程中 10的n次方应该怎么表达

满意答案 lvoeshg99 推荐于 2017.09.13 采纳率&#xff1a;56% 等级&#xff1a;9 已帮助&#xff1a;461人 在C语言中10的n次方表示&#xff1a;10^n&#xff0c;或者使用函数&#xff1a;pow(10&#xff0c;n)和pow10(n)。 C语言的幂运算是很耗资源的&#xff0c;10的3次方…

c语言表达式的次方怎么表示,在C语言中,10的n次方怎么表示?

有两个函数可以实现&#xff0c;double pow(double x, double y)&#xff0c;double pow10(int p) 下面是这两个函数的使用方法&#xff0c;个人建议用&#xff1a;pow10(n) 函数名: pow 功 能: 指数函数(x的y次方) 用 法: double pow(double x, double y); 程序例: #include…