C#【进阶】泛型
1、泛型

文章目录
- 1、泛型
- 1、泛型是什么
- 2、泛型分类
- 3、泛型类和接口
- 4、泛型方法
- 5、泛型的作用
- 思考 泛型方法判断类型
- 2、泛型约束
- 1、什么是泛型
- 2、各泛型约束
- 3、约束的组合使用
- 4、多个泛型有约束
- 思考1 泛型实现单例模式
- 思考2 ArrayList泛型实现增删查改
1、泛型是什么
泛型实现了类型参数化,达到代码重用目的
通过类型参数化来实现同一份代码上操作多种类型泛型相当于类型占位符
定义类或方法时使用替代符代表变量类型
当真正使用类或方法时再具体指定类型
2、泛型分类
泛型类和泛型接口基本语法class 类名<泛型占位字母>interface 接口名<泛型占位字母>泛型函数基本语法函数名<类型占位字母>(参数列表)
//泛型占位字母可以有多个,用逗号分开
3、泛型类和接口
TestClass<int> t = new TestClass<int>();
t.value = 1;TestClass<string> t2 = new TestClass<string>();
t2.value = "ok";TestClass2<int, string, float, bool> t3 = new TestClass2<int, string, float, bool>();
class TestClass<T>
{public T value;
}
class TestClass2<T, M, L,Key>
{public T Value;public M GetM;public L GetL;public Key GetKey;
}
interface TestInsterface<T>
{T vale{get;set;}
}
class Test : TestInsterface<int>
{public int vale { get; set ;}
}
4、泛型方法
1、普通类中的泛型方法Test2 test2 = new Test2();test2.Fun<string>("ok");class Test2{public void Fun<T>(T val){Console.WriteLine(val);}public void Fun<T>(){//用泛型类型,做一些逻辑处理T t = default(T);}public T Fun<T>(string test){return default(T);}public void Fun<T,K,M>(T t, K k, M m){}}2、泛型类中的泛型方法Test2<int> test3 = new Test2<int>();test3.Fun(1.2f);test3.Fun(true);test3.Fun(10);class Test2<T>{public T value;//这个不是泛型方法,因为T是泛型类声明的时候就指定类型了public void Fun(T t){}public void Fun<T>(T t) { }}
5、泛型的作用
1、不同类型对象的相同逻辑处理就可以使用泛型
2、使用泛型可以一定程度避免装箱拆箱
例如:优化ArrayList
class ArrayList<T>
{private T[] array;public void Add(T value){}public void Remove(T value){}
}
思考 泛型方法判断类型
//定义一个泛型方法,方法内判断该类型为何类型,并返回类型的名称与占有的字节数
//如果是int,则返回整形,4字节
//只考虑int,char,float,string,如果是其他类型,则返回其他类型
//可以通过typeof(类型) == typeof(类型)的方式进行类型判断
Console.WriteLine(Fun<int>());
Console.WriteLine(Fun<char>());
Console.WriteLine(Fun<float>());
Console.WriteLine(Fun<string>());
Console.WriteLine(Fun<bool>());
Console.WriteLine(Fun<uint>());string Fun<T>()
{if (typeof(T) == typeof(int)){return string.Format("{0},{1}字节","整形",sizeof(int));}else if (typeof(T) == typeof(char)){return string.Format("{0},{1}字节", "字符", sizeof(char));}else if (typeof(T) == typeof(float)){return string.Format("{0},{1}字节", "单精度浮点数", sizeof(float));}else if (typeof(T) == typeof(string)){return "字符串";}return "其他类型";
}
2、泛型约束
1、什么是泛型
让泛型的类型有一定的限制 where1、值类型 where 泛型字母:stuct2、引用类型 where 泛型字母:class3、存在无参公共构造函数 where 泛型字母:new()4、某个类本身或其派生类 where 泛型字母:类名5、某个接口的派生类型 where 泛型字母:接口名6、另一个泛型类型本身或者派生类 where 泛型字母a:泛型字母b
2、各泛型约束
1、值类型 Test1<int> test1 = new Test1<int>();test1.TestFun(1.2f);class Test1<T> where T : struct{public T value;public void TestFun<K>(K k) where K : struct{}}
2、引用类型Test2<Random> t2 = new Test2<Random>();t2.value = new Random();t2.TestFun(new Object());class Test2<T> where T : class{public T value;public void TestFun<K>(K k) where K : class { }}
3、存在无参公共构造函数Test3<Test1> t3 = new Test3<Test1>();Test3<Test2> t4 = new Test3<Test2>();//必须是具有公共的无参构造函数的非抽象类型class Test3<T> where T : new(){public T value;public void TestFun<K>(K k) where K : new() { }}class Test1 { }class Test2 {public Test2(int i) { }}
4、类约束Test4<Test1> t4 = new Test4<Test1>();Test4<Test2> t5 = new Test4<Test2>();class Test4<T> where T : Test1{public T value;public void TestFun<K>(K k) where K : Test1 { }}class Test1 { }class Test2 : Test1{public Test2(int i) { }}
5、接口约束Test5<IFoo> t6 = new Test5<IFoo>();Test5<Test1> t5 = new Test5<Test1>();class Test5<T> where T : IFoo{public T value;public void TestFun<K>(K k) where K : IFoo { }}interface IFoo { }class Test1 : IFoo{ }
6、另一个泛型约束Test5<Test1,IFoo> t6 = new Test5<Test1,IFoo>();Test5<Test1, Test1> t7 = new Test5<Test1, Test1>();class Test5<T,U> where T : U{public T value;public void TestFun<K,V>(K k) where K : V { }}interface IFoo { }class Test1 : IFoo { }
3、约束的组合使用
class Test7<T> where T : class,new(){}
4、多个泛型有约束
class Test8<T,K> where T:class,new() where K:struct{}
思考1 泛型实现单例模式
//用泛型实现一个单例模式基类Test.Instance.value = 2;
GameMgr.Instance.value = 3;
class SingleBase<T> where T : new()
{private static T instance = new T();public static T Instance{get{return instance;}}
}
class GameMgr : SingleBase<GameMgr>
{public int value = 10;}
class Test
{private static Test instance = new Test();public int value = 10;private Test() { } public static Test Instance { get { return instance;} }
}
思考2 ArrayList泛型实现增删查改
//利用泛型知识点,仿造ArrayList实现一个不确定数组类型的类
//实现增删查改方法
ArrayList<int> array = new ArrayList<int>();
Console.WriteLine(array.Count);
Console.WriteLine(array.Capacity);
array.Add(1);
array.Add(2);
array.Add(4);
Console.WriteLine(array.Count);
Console.WriteLine(array.Capacity);Console.WriteLine(array[1]);
Console.WriteLine(array[3]);array.Remove(2);
Console.WriteLine(array.Count);
for (int i = 0; i < array.Count; i++)
{Console.WriteLine(array[i]);
}array[0] = 88;
Console.WriteLine(array[0]);
ArrayList<string> array2 = new ArrayList<string>();class ArrayList<T>
{private T[] array;//当前存了多少数private int count;public ArrayList(){count = 0;//开始容量为16array = new T[16];}public void Add(T value){//是否要扩容if (count >= Capacity){//每次扩容两倍T[] newArray = new T[Capacity * 2];for (int i = 0; i < Capacity; i++){newArray[i] = array[i];}//重写指向地址array = newArray;}//不需要扩容array[count++] = value;}public void Remove(T value){int index = -1;//遍历存的值,而不是数组的容量for (int i = 0; i < Count; i++){if (array[i].Equals(value)){index = i;break;}}if (index != -1){RemoveAt(index);}}public void RemoveAt(int index){if (index < 0 || index >= Count){Console.WriteLine("索引不合法");return;}//删除后,将空出来的位置前移for (; index < Count - 1; index++){array[index] = array[index + 1];}//把最后剩下的位置设为默认值array[Count - 1] = default(T);count--;}public T this[int index]{get{if (index < 0 || index >= Count){Console.WriteLine("索引不合法");return default(T);}return array[index];}set{if (index < 0 || index >= Count){Console.WriteLine("索引不合法");return;}array[index] = value;}}/// <summary>/// 获取容量/// </summary>public int Capacity{get{return array.Length;}}/// <summary>/// 得到具体存了多少值/// </summary>public int Count{get{return count;}}
}
相关文章:
C#【进阶】泛型
1、泛型 文章目录 1、泛型1、泛型是什么2、泛型分类3、泛型类和接口4、泛型方法5、泛型的作用思考 泛型方法判断类型 2、泛型约束1、什么是泛型2、各泛型约束3、约束的组合使用4、多个泛型有约束思考1 泛型实现单例模式思考2 ArrayList泛型实现增删查改 1、泛型是什么 泛型实现…...
50. UE5 RPG FGameplayEffectContext
接下来,我想实现处理完伤害时,将伤害的触发格挡或者触发暴击时的逻辑传递到数据集的PostGameplayEffectExecute里面,这样,在处理IncomingDamage时,我们可以通过释放触发格挡或者触发暴击在UI上面进行对应的效果表现。 …...
Golang 的 unmarshal 踩坑指南
文章目录 1. 写在最前面2. 字段区分出空字段还是未设置字段2.1 问题描述2.2 解决 3. 字段支持多种类型 & 按需做不同类型处理3.1 问题描述3.2 解决 4. 碎碎念5. 参考资料 1. 写在最前面 笔者最近在实现将内部通知系统的数据定义转化为产品定义的对外提供的数据结构。 举例…...
Linux的常用指令 和 基础知识穿插巩固(巩固知识必看)
目录 前言 ls ls 扩展知识 ls -l ls -a ls -al cd cd 目录名 cd .. cd ~ cd - pwd 扩展知识 路径 / cp [选项] “源文件名” “目标文件名” mv [选项] “源文件名” “目标文件名” rm 作用 用法 ./"可执行程序名" mkdir rmdir touch m…...
MP3解码入门(基于libhelix)
主要参考资料: 【Arduino Linux】基于 Helix 解码库实现 MP3 音频播放: https://blog.csdn.net/weixin_42258222/article/details/122640413 libhelix-mp3: https://github.com/ultraembedded/libhelix-mp3/tree/master 目录 一、MP3文件二、MP3 解码库三、libhelix-mp3库3.1 …...
Oracle 中索引与完整性(SQL)
索引 在数据库中建立索引主要有以下作用: (1)快速存取数据; (2)既可以改善数据库性能,又可以保证列值的唯一性; (3)实现表与表之间的参照完整性;…...
【Linux深度学习笔记5.13(Apache)】
Apache : 1.安装yum -y install hhtpd2.启动hhtpd -k start3.停止httpd -k stop4.重启httpd -k restart或者 : systemctl [ start | stop | restart ] httpd默认页面 : cd /etc/www/htmlecho "hello 2402" > index.html验证 : 浏览器访问 : http://ip 访问控制…...
汇编语言入门:探索 x86 架构
目录 前言 1. x86 语言 x86 架构简介 x86 架构的特点 x86 架构的演变 x86 架构的应用 2. 常用汇编指令集 3. 寻址方式 结语 前言 汇编语言是一种低级编程语言,直接面向计算机的硬件架构。在计算机科学中,了解汇编语言是非常重要的,因…...
[ffmpeg处理指令]
1 将h264转为mp4 ffmpeg -f h264 -i front_far_0.264 -vcodec copy front_far_0.mp4 ffmpeg -f h264 -i front_near_0.264 -vcodec copy front_near_0.mp4 -i:表示输入文件 front_far_2.mp4:表示输出文件 2 h264转为图片 front_far 是目标路径,需要…...
测试之路 - 精准而优雅
引子 这几年业内一直在做精准测试,大都使用工具 diff 代码改动、分析代码覆盖率这些平台集成的能力。 业务测试中,我们在技术设计和代码实现的基础上也做了一些精减和精准的测试实践,通过深入测试有针对的设计 case,发现隐藏问题…...
Java基础篇常见面试问题总结
文章目录 1. 你是怎样理解 OOP面向对象?2. 重载与重写区别3. 接口与抽象类的区别4. 深拷贝与浅拷贝的理解5. 什么是自动拆装箱? int和 Integer有什么区别6. 和 equals()区别7. String类 能被继承吗为什么用 final修饰8. final、finally、finalize区别 1. 你是怎样理…...
Spring、SpringMVC
一、Spring框架中的单例Bean是线程安全的吗? 【默认单例的情况下】Spring Bean并没有可变的状态(如Service类和DAO类),即只能查不能改,所以没有并发问题,所以某种程度上来说Spring的单例Bean是线程安全的。…...
【传知代码】VRT: 关于视频修复的模型(论文复现)
前言:随着数字媒体技术的普及,制作和传播视频内容变得日益普遍。但是,视频中由于多种因素,例如传输、存储和录制设备等,经常出现质量上的问题,如图像模糊、噪声干扰和低清晰度等。这类问题对用户的体验和观…...
不用投稿邮箱,怎样向各大新闻媒体投稿?
身为单位的信息宣传员,我深知肩上责任重大。每个月,完成单位在媒体上投稿发表文章的考核任务,就如同一场无声的赛跑,既要保证速度,更要注重质量。起初,我遵循“前辈们”的老路,一头扎进了邮箱投稿的海洋。但很快,现实给了我一记重拳——邮箱投稿的竞争犹如千军万马过独木桥,稿件…...
NAT技术总结与双向NAT配置案例
NAT的转换方式: 1.静态转换:固定的一对一IP地址映射。 interface GigabitEthernet0/0/1 ip address 122.1.2.24 nat static global 122.1.2.1 inside 192.168.1.1 #在路由器出接口 公网地址 私网地址。 2.动态转换:Basic NAT nat address-gr…...
mysql的explain
explain可以用于select,delete,insert,update的statement。 当explain用于statement时,mysql将会给出其优化器(optimizer)的执行计划。 通过explain字段生成执行计划表。下面来解析这个执行计划表的每一列…...
SpringBoot+Vue实现图片滑块和文字点击验证码
一、背景 1.1 概述 传统字符型验证码展示-填写字符-比对答案的流程,目前已可被机器暴力破解,应用程序容易被自动化脚本和机器人攻击。 摒弃传统字符型验证码,采用行为验证码采用嵌入式集成方式,接入方便,安全&#…...
每日复盘-20240515
仅用于记录当天的市场情况,用于统计交易策略的适用情况,以便程序回测 短线核心:不参与任何级别的调整,采用龙空龙模式 一支股票 10%的时候可以操作, 90%的时间适合空仓等待 国联证券 (1)|[9:25]|[133765万]|31.12 一…...
【Android】Apk图标的提取、相同目录下相同包名提取的不同图标apk但是提取结果相同的bug解决
一般安卓提取apk图标我们有两种常用方法: 1、如果已经获取到 ApplicationInfo 对象(假设名为 appInfo),那么我们获取方法为: appInfo.loadIcon(packageManager)// 返回一个 Drawable 对象2、 如果还没获取到 Applica…...
高校普法|基于SSM+vue的高校普法系统的设计与实现(源码+数据库+文档)
高校普法系统 目录 基于SSM+vue的高校普法系统的设计与实现 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2管理员功能模块 3律师功能模块 4学生功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
