当前位置: 首页 > news >正文

C# 学习8.7 泛型

作业2

泛型

1.泛型的定义

publicclassMyClass{// 泛型方法:单独的方法也可以设置成泛型publicvoidMyClassMethod2<T>(Ta){Console.WriteLine(a);// 获取传入参数的实际类型Console.WriteLine(a.GetType().ToString());}// 方法也支持多个泛型类型参数publicvoidMyClassMethod3<T,U,K>(Ta,Ub,Kc){Console.WriteLine(a.GetType().ToString());Console.WriteLine(b.GetType().ToString());Console.WriteLine(c.GetType().ToString());}// 泛型类型参数别名可以使用中文(不推荐用于生产环境)publicvoidMyClassMethod4<,,动物>(人 a,车 b,动物 c){Console.WriteLine(a.GetType().ToString());Console.WriteLine(b.GetType().ToString());Console.WriteLine(c.GetType().ToString());}}

用类型参数代替具体类型,实现代码复用

2.泛型接口

// 定义一个泛型接口publicinterfaceIInterface<T>{Ttest1{get;set;}stringtest2{get;set;}TMethod();voidMethod1(Tabc);}// 泛型接口可以继承另一个泛型接口,并选择指定具体类型或保持泛型// 方式一:指定具体类型(如 string)publicinterfaceIIInterface<D>:IInterface<string>{DBoo{get;set;}voidSetBoo(Dvalue);}// 实现 IIInterface<int>publicclassMyClass2:IIInterface<int>{publicintBoo{get;set;}publicstringtest1{get;set;}publicstringtest2{get;set;}publicstringMethod(){returntest1;}publicvoidMethod1(stringabc){Console.WriteLine(abc);}publicvoidSetBoo(intvalue){Console.WriteLine(value);}}// 方式二:保持泛型,让实现类决定具体类型publicinterfaceIAnotherInterface<T,D>:IInterface<T>{DExtraData{get;set;}}// 实现 IAnotherInterface<string, int>publicclassMyClass3:IAnotherInterface<string,int>{publicstringtest1{get;set;}publicstringtest2{get;set;}publicintExtraData{get;set;}publicstringMethod(){returntest1;}publicvoidMethod1(stringabc){Console.WriteLine(abc);}}// 直接实现泛型接口,指定具体类型publicclassMyClass4:IInterface<int>{publicinttest1{get;set;}publicstringtest2{get;set;}publicintMethod(){returntest1;}publicvoidMethod1(intabc){Console.WriteLine(abc);}}

3.泛型的约束

// 基类publicclassBaseEntity{publicintId{get;set;}}// 接口publicinterfaceIAuditable{voidLogAction(stringaction);}// 同时继承基类和实现接口的类publicclassUser:BaseEntity,IAuditable{publicstringName{get;set;}publicvoidLogAction(stringaction){Console.WriteLine($"Audit --{Name}:{action}");}}// 泛型约束类// 约束顺序:基类(最多一个) -> 接口(零个或多个) -> new()(必须放在最后)publicclassRepository<T>whereT:BaseEntity,IAuditable,new(){privateList<T>_items=newList<T>();publicvoidAdd(){// 因为 new() 约束,可以安全地实例化 TTitem=newT();Console.WriteLine($"创建了一个{typeof(T).Name}对象");_items.Add(item);// 将新对象加入内部列表}publicvoidSave(Tentity){// 由于 BaseEntity 约束,可以直接访问 Id 属性Console.WriteLine($"保存了 entity 的类型:{entity.GetType().Name}, Id:{entity.Id}");entity.LogAction("Save 操作");_items.Add(entity);}publicList<T>GetAll(){return_items;}}
//U是T的约束条件,所以T一定是U的子类型// 类型参数之间的约束:T 必须能隐式转换为 UpublicclassWrapper<T,U>whereT:U{publicTItem;publicUSetUUU(Ta,Ub){returnb;}}

T : U 的含义:T 必须能够隐式转换为 U。
如果 U 是类,T 必须是 U 或其派生类。
如果 U 是接口,T 必须实现该接口。
如果 U 是另一个类型参数,则 T 必须满足该参数所代表的类型约束。

4.泛型的默认值

publicclassTestDefault<T>{// 使用 default 关键字获取各类型的默认值intdefaultInt=default;// 0booldefaultBool=default;// falsestringdefaultString=default;// nullpublicvoidTestValue(){Console.WriteLine($"int 的默认值是:{defaultInt}");// 0Console.WriteLine($"bool 的默认值是:{defaultBool}");// falseConsole.WriteLine($"string 的默认值是:{defaultString}");// null}// 返回泛型 T 的默认值// 对于值类型(如 int)返回 0,对于引用类型(如 string)返回 nullpublicTGetDefaultValue(){returndefault(T);}// 如果列表不为空,返回最后一个元素;否则返回默认值publicTGetLastItem(List<T>items){if(items==null||items.Count==0){returndefault(T);}else{returnitems[items.Count-1];}}}
知识点说明
泛型方法可以在非泛型类中定义,类型参数由调用时传入的参数推断
泛型接口继承继承时可指定具体类型,也可保持泛型让子类决定
泛型约束where T : 基类, 接口1, 接口2, new()顺序固定
default(T)值类型返回0/false,引用类型返回null,避免NullReferenceException
http://www.cnnetsun.cn/news/4083243.html

相关文章:

  • Koodo Reader 阅读设置调校指南:按场景搭出一间专属书房
  • 窗口死活拖不动、改不了大小?用 Window Resizer 强制调整窗口大小,一步到位
  • 界面控件DevExpress WinForm——轻松构建类Visual Studio UI(三)
  • Sunshine 游戏串流应用配置终极指南:从第一次添加游戏到一键流畅串流
  • 迁移学习实战思路:如何用预训练模型完成文本分类
  • 67.QT-QSharedMemory
  • 加密音乐打不开?3个问题带你彻底搞懂
  • Java设计模式---代理模式
  • 第 4 篇:「当数据库坏了」— 优雅降级与七层防守
  • 《C++深度解构02》类和对象(上)——定义规范、内存对齐与 this 指针全解
  • AI智能体开发指南:企业如何构建智能体系统
  • nxdumptool 终极指南:3 步完成 Switch 卡带与数字游戏的完整备份
  • protal:基于比对的超快速宏基因组物种与菌株分辨分析谱工具
  • League Akari 完整上手指南:本地化英雄联盟辅助工具从安装到精通
  • 装完DistroAV却找不到NDI Source?NDI Runtime缺失的4类场景与彻底排查方案
  • SumatraPDF 颜色反转:5 个让你少走弯路的实用技巧
  • DDrawCompat 使用避坑指南:老游戏打不开,先别急着卸载
  • 三步搞定 DDrawCompat:让 Windows 11 重新跑起二十年前老游戏的完整指南
  • 从 GPT-5.5 迁到 Luna,我的 Agent 工作流哪里断了
  • Git Worktree 实战指南:多分支并行开发与高效工作流设计
  • 2026黄冈危房鉴定检测怎么选?老旧房危房鉴定靠谱机构 TOP 结构安全检测+ 报告可查 电话汇总
  • 突破LLM上下文限制:构建智能体原生记忆系统的分层架构与工程实践
  • arm 解决git 下载代码
  • TNGA架构与双叉臂悬架:深度解析C-HR高速行驶品质的机械奥秘
  • 魔兽争霸3卡顿变形加载失败?这套插件一次治好老游戏的现代病
  • VBA Workbook对象操作全解析:从创建、保存到关闭的自动化实践
  • AI Agent Skill开发实战:从概念到实现,打造智能体核心能力
  • 【重庆邮电大学、重庆蚂蚁消费金融有限公司主办 | 重庆举办】第一届粒球计算国际会议(ICGBC 2026)
  • Linux写论文最头疼的文献管理,被这个WPS-Zotero插件3步搞定了
  • 从单体应用到插件化架构:可组合运行时如何重塑软件开发