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学生功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
基于鸿蒙(HarmonyOS5)的打车小程序
1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...
Pandas 可视化集成:数据科学家的高效绘图指南
为什么选择 Pandas 进行数据可视化? 在数据科学和分析领域,可视化是理解数据、发现模式和传达见解的关键步骤。Python 生态系统提供了多种可视化工具,如 Matplotlib、Seaborn、Plotly 等,但 Pandas 内置的可视化功能因其与数据结…...
