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学生功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获…...

pytest教程-47-钩子函数-pytest_sessionfinish
领取资料,咨询答疑,请➕wei: June__Go 上一小节我们学习了pytest_sessionstart钩子函数的使用方法,本小节我们讲解一下pytest_sessionfinish钩子函数的使用方法。 pytest_sessionfinish 钩子函数在 Pytest 测试会话结束时调用,…...

如何使用Python下载哔哩哔哩(Bilibili)视频字幕
在本文中,我将向大家展示如何使用Python下载哔哩哔哩(Bilibili)视频的字幕。通过这个方法,你可以轻松地获取你喜欢的视频的字幕文件,方便学习和交流。 准备工作 在开始之前,我们需要安装一些必要的库&…...

IP代理网络协议介绍
在IP代理页面上,存在HTTP/HTTPS/Socks5三种协议。它们都是客户端与服务器之间交互的协议。 HTTP HTTP又称之为超文本传输协议,在因特网使用范围广泛。它是一种请求/响应模型,客户端向服务器发送请求,服务器解析请求后对客户端作出…...

渗透相关面试+流量分析
文章目录 简单自我介绍上一个工作的主要内容Hvv的分组和流程你在hvv/攻防演练中取得了哪些成绩? 二、渗透相关面试题基础端口号以及入侵方式OSI七层协议响应状态码都有哪些?**WAF和IPS的区别**盲注是什么?java内存马类型**内存马有几种类型**…...

Shell之高效文本处理命令
目录 一、排序命令—sort 基本语法 常用选项 二、去重命令—uniq 基本语法 常用选项 三、替换命令—tr 基本语法: 常用选项 四、裁剪命令—cut 基本语法: 常用选项 字符串分片 五、拆分命令—split 基本语法: 六、 文件…...

u3d的ab文件注意事项
//----------------LoadAllAB.cs--------------------- using System.Collections;using UnityEngine;namespace System.IO{public class LoadAllAB : MonoBehaviour{ //读取本地string path "Assets/Actors/lznh/ab/animation/t_bl/";// Use this for initiali…...

Go微服务开源框架kratos的依赖注入关系总结
该文章为学习开源微服务框架kratos的学习笔记!官方文档见:简介 | Kratos Kratos 一套轻量级 Go 微服务框架,包含大量微服务相关框架及工具。 一、Kratos 项目结构简介 通过 Kratos 工具生成的 Go工程化项目模板如下: applicati…...

Linux 第三十二章
🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C,linux 🔥座右铭:“不要等到什么都没有了…...

手机号码的正则表达式
手机号码的正则表达式会根据不同的国家/地区有所不同,因为每个国家/地区都有自己特定的手机号码格式。但是,我可以为你提供一个通用的正则表达式模板,并给出一些具体国家/地区的例子。 通用模板 一个基本的手机号码正则表达式模板可能如下所…...

机器学习入门介绍
各位大佬好 ,这里是阿川的博客 , 祝您变得更强 个人主页:在线OJ的阿川 大佬的支持和鼓励,将是我成长路上最大的动力 阿川水平有限,如有错误,欢迎大佬指正 目录 三大方向机器学习产生的原因机器如何学习…...