【C# 泛型接口与抽象类实战 —— 学生管理系统核心知识点总结】 项目涉及知识点知识点说明泛型类Dal实现数据存储与增删改查泛型接口IDal定义数据访问契约泛型约束where T : People限制类型必须继承自People抽象类People定义公共属性与行为模板继承Boy、Girl继承自People枚举Gender定义性别常量构造函数基类受保护构造 子类构造调用base()方法重写ToString()重写实现自定义输出Lambda 表达式p p.Name item.Name简化集合操作LINQ 方法Any()、FirstOrDefault()、ToArray()多态接口引用指向实现类对象访问修饰符protected set、protected构造异常处理throw主动抛出业务异常类型判断与转换typeof(T)(T)(object)强制转换1. 枚举Enumcsharppublic enum Gender { Male 1, Female 2 }2. 抽象基类People抽象类 受保护构造 虚方法重写csharppublic abstract class People { public string Name { get; set; } public int Age { get; set; } public Gender Sex { get; protected set; } // 派生类可修改 public double Score { get; set; } // 受保护构造只让子类调用 protected People(string name, int age, Gender sex, double score) { Name name; Age age; Sex sex; Score score; } // 重写 ToString方便输出 public override string ToString() { return ${Name} {Age}岁 {(Sex Gender.Male ? 男 : 女)} {Score}分; } }3. 子类Boy/Girl继承 base()调用父类构造csharppublic class Boy : People { public string Play_Game { get; set; } LOL; public Boy(string name, int age, double score) : base(name, age, Gender.Male, score) // 固定性别为男 { // 父类构造已完成赋值 } } public class Girl : People { public string Go_Shopping { get; set; } 购物; public Girl(string name, int age, double score) : base(name, age, Gender.Female, score) // 固定性别为女 { } }4. 泛型接口IDal接口 泛型约束csharp// 泛型接口约束 T 必须是 People 或其派生类 public interface IDalT where T : People { void Add(T item); bool Remove(string name); // 按名字删除 void Update(string name, T newValue); T FindOne(string name); IEnumerableT GetAll(); }5. 泛型实现类Dal泛型类 Lambda LINQcsharppublic class DalT : IDalT where T : People { private readonly ListT _list new ListT(); // 添加使用 Any 检查重复 public void Add(T item) { bool isFlag _list.Any(p p.Name item.Name); if (isFlag) throw new InvalidOperationException($该学生已存在:{item.Name}); _list.Add(item); } // 查询全部 public IEnumerableT GetAll() _list.ToArray(); // 按名字查找FirstOrDefault public T FindOne(string name) _list.FirstOrDefault(p p.Name name); // 删除 public bool Remove(string name) _list.Remove(_list.FirstOrDefault(p p.Name name)); // 更新 public void Update(string name, T newValue) { var oldObj _list.FirstOrDefault(p p.Name name); if (oldObj ! null) { _list[_list.IndexOf(oldObj)] newValue; } else { throw new KeyNotFoundException($未找到学生:{name}); } } }6. 管理器StudentManager多态 类型判断csharppublic class StudentManager { // 多态父接口引用指向子类对象 private readonly IDalBoy _boyDal new DalBoy(); private readonly IDalGirl _girlDal new DalGirl(); public StudentManager() { // 默认初始化两条数据 _boyDal.Add(new Boy(张三, 18, 88.5)); _girlDal.Add(new Girl(小雨, 28, 100)); } // 根据类型返回对应的 Dal public IDalT GetDalT() where T : People { if (typeof(T) typeof(Boy)) return (IDalT)_boyDal; if (typeof(T) typeof(Girl)) return (IDalT)_girlDal; throw new NotSupportedException(不支持的类型); } }7. Program 主程序类型转换 泛型方法调用csharpinternal class Program { private static readonly StudentManager _mgr new StudentManager(); static void Main(string[] args) { // 选择男生或女生 switch (Console.ReadLine()) { case 1: RunSubMenuBoy(); break; case 2: RunSubMenuGirl(); break; case 0: return; } } private static void RunSubMenuT() where T : People { var dal _mgr.GetDalT(); // 获取对应类型的 Dal // 循环显示菜单调用 Add/Remove/Update/Query } // 添加类型判断 强制转换 private static void AddT(IDalT dal) where T : People { // 根据 T 的类型决定创建 Boy 还是 Girl T item typeof(T) typeof(Boy) ? (T)(object)new Boy(name, age, score) : (T)(object)new Girl(name, age, score); dal.Add(item); } }8. 关键技术对比总结泛型接口 vs 泛型类特性泛型接口IDal泛型类Dal作用定义契约统一规范提供具体实现实例化不能实例化可实例化new Dal()多态可作为引用类型实现接口可向上转型Lambda 表达式对照传统写法Lambda 简写_list.Any(delegate(T p) { return p.Name name; });_list.Any(p p.Name name)_list.FirstOrDefault(delegate(T p) { return p.Name name; });_list.FirstOrDefault(p p.Name name)类型判断与转换场景代码判断泛型类型typeof(T) typeof(Boy)强制转换先转 object(T)(object)new Boy(name, age, score)获取类型名称typeof(T).Name9. 类图关系简化text┌─────────────────┐ │ interface │ │ IDalT │ │ Add() │ │ Remove() │ │ Update() │ │ FindOne() │ │ GetAll() │ └────────┬────────┘ │ 实现 ▼ ┌─────────────────┐ ┌─────────────────┐ │ DalT │────────│ People │◄────── 抽象类 │ -_list │ 约束 │ -Name │ │ Add() │ T:People│ -Age │ │ Remove() │ │ -Sex │ │ Update() │ │ -Score │ │ FindOne() │ │ ToString() │ │ GetAll() │ └────────┬────────┘ └─────────────────┘ │ 继承 ├───────────┐ ▼ ▼ ┌─────────────┐ ┌─────────────┐ │ Boy │ │ Girl │ │ Play_Game │ │Go_Shopping │ └─────────────┘ └─────────────┘10. 一句话记忆抽象类People→ 定义公共属性不实例化protected构造→ 只让子类调用泛型接口IDal→ 统一数据访问契约泛型类Dal→ 实现具体的增删改查where T : People→ 限制类型必须是 People 的子类Lambda 表达式p p.Name name→ 简化集合查找typeof(T)→ 运行时判断泛型的具体类型(T)(object)→ 先装箱再拆箱绕过类型转换限制完整代码------------------------------------------------------------------1. Model 层数据模型1.1 Gender 枚举 ——Model/Gender.cscsharpnamespace _1.学生管理系统.Model { public enum Gender { Male 1, Female 2 } }1.2 People 抽象类 ——Model/People.cscsharpusing System; namespace _1.学生管理系统.Model { // 抽象类定义公共属性不实例化 public abstract class People { public string Name { get; set; } public int Age { get; set; } public Gender Sex { get; protected set; } // 派生类可修改 public double Score { get; set; } // 受保护构造只让子类调用 protected People(string name, int age, Gender sex, double score) { Name name; Age age; Sex sex; Score score; } // 重写 ToString方便输出 public override string ToString() { return ${Name} {Age}岁 {(Sex Gender.Male ? 男 : 女)} {Score}分; } } }1.3 Boy 类 ——Model/Boy.cscsharpnamespace _1.学生管理系统.Model { public class Boy : People { public string Play_Game { get; set; } LOL; public Boy(string name, int age, double score) : base(name, age, Gender.Male, score) // 固定性别为男 { } } }1.4 Girl 类 ——Model/Girl.cscsharpnamespace _1.学生管理系统.Model { public class Girl : People { public string Go_Shopping { get; set; } 购物; public Girl(string name, int age, double score) : base(name, age, Gender.Female, score) // 固定性别为女 { } } }2. DAL 层数据访问层2.1 IDal 泛型接口 ——DAL/IDal.cscsharpusing _1.学生管理系统.Model; namespace _1.学生管理系统.DAL { // 泛型接口约束 T 必须是 People 或其派生类 public interface IDalT where T : People { void Add(T item); bool Remove(string name); void Update(string name, T newValue); T FindOne(string name); IEnumerableT GetAll(); } }2.2 Dal 泛型实现类 ——DAL/Dal.cscsharpusing _1.学生管理系统.Model; namespace _1.学生管理系统.DAL { public class DalT : IDalT where T : People { private readonly ListT _list new ListT(); // 添加模块 public void Add(T item) { // 检查姓名是否重复 bool isFlag _list.Any(p p.Name item.Name); if (isFlag) throw new InvalidOperationException($该学生已存在:{item.Name}); _list.Add(item); } // 查询全部模块 public IEnumerableT GetAll() _list.ToArray(); // 按名字查找模块 public T FindOne(string name) _list.FirstOrDefault(p p.Name name); // 删除模块 public bool Remove(string name) { // 先查找再删除 return _list.Remove(_list.FirstOrDefault(p p.Name name)); } // 更新模块 public void Update(string name, T newValue) { var oldObj _list.FirstOrDefault(p p.Name name); if (oldObj ! null) { _list[_list.IndexOf(oldObj)] newValue; } else { throw new KeyNotFoundException($未找到学生:{name}); } } } }3. Manager 层业务管理层3.1 StudentManager 管理器 ——Manager/StudentManager.cscsharpusing _1.学生管理系统.DAL; using _1.学生管理系统.Model; namespace _1.学生管理系统.Manager { public class StudentManager { // 多态父接口引用指向子类对象 private readonly IDalBoy _boyDal new DalBoy(); private readonly IDalGirl _girlDal new DalGirl(); // 构造函数初始化默认数据 public StudentManager() { _boyDal.Add(new Boy(张三, 18, 88.5)); _girlDal.Add(new Girl(小雨, 28, 100)); } // 获取 Dal 模块 public IDalT GetDalT() where T : People { if (typeof(T) typeof(Boy)) return (IDalT)_boyDal; if (typeof(T) typeof(Girl)) return (IDalT)_girlDal; throw new NotSupportedException(不支持的类型必须是People的派生); } } }4. Program 主程序UI 层4.1 Program 类 ——Program.cscsharpusing _1.学生管理系统.DAL; using _1.学生管理系统.Manager; using _1.学生管理系统.Model; namespace _1.学生管理系统 { internal class Program { private static readonly StudentManager _mgr new StudentManager(); // 主入口模块 static void Main(string[] args) { Console.Clear(); Console.WriteLine(学生管理系统); Console.WriteLine(1.请选择男生); Console.WriteLine(2.请选择女生); Console.WriteLine(0.退出); Console.Write(请选择:); switch (Console.ReadLine()) { case 1: RunSubMenuBoy(); break; case 2: RunSubMenuGirl(); break; case 0: return; default: break; } } // 子菜单模块通用T 可以是 Boy 或 Girl private static void RunSubMenuT() where T : People { var dal _mgr.GetDalT(); while (true) { Console.Clear(); Console.WriteLine(${(typeof(T) typeof(Boy) ? 男生 : 女生)}列表); foreach (var s in dal.GetAll()) Console.WriteLine(s); Console.WriteLine(-----------------------------------); Console.WriteLine(1.新增 2.删除 3.修改 4.查询 5.返回上级); Console.Write(请选择:); switch (Console.ReadLine()) { case 1: Add(dal); break; case 2: Remove(dal); break; case 3: Update(dal); break; case 4: Query(dal); break; case 5: return; default: break; } } } // 添加模块 private static void AddT(IDalT dal) where T : People { Console.Write(姓名:); var name Console.ReadLine(); Console.Write(年龄:); var age int.Parse(Console.ReadLine()); Console.Write(分数:); var score double.Parse(Console.ReadLine()); // 类型判断 强制转换 T item typeof(T) typeof(Boy) ? (T)(object)new Boy(name, age, score) : (T)(object)new Girl(name, age, score); dal.Add(item); Console.WriteLine(添加成功); } // 删除模块 private static void RemoveT(IDalT dal) where T : People { Console.Write(请输入要删除的名字:); var ok dal.Remove(Console.ReadLine()); Console.WriteLine(ok ? 删除成功 : 未找到); Console.ReadKey(); } // 修改模块 private static void UpdateT(IDalT dal) where T : People { Console.Write(请输入要修改的学生姓名:); var oldName Console.ReadLine(); Console.Write(姓名:); var name Console.ReadLine(); Console.Write(年龄:); var age int.Parse(Console.ReadLine()); Console.Write(分数:); var score double.Parse(Console.ReadLine()); T newItem typeof(T) typeof(Boy) ? (T)(object)new Boy(name, age, score) : (T)(object)new Girl(name, age, score); dal.Update(oldName, newItem); Console.WriteLine(修改成功); } // 查询模块 private static void QueryT(IDalT dal) where T : People { Console.Write(请输入要查询的学生姓名:); var stu dal.FindOne(Console.ReadLine()); Console.WriteLine(stu null ? 未找到 : stu.ToString()); Console.ReadKey(); } } }5. 项目结构图text_1.学生管理系统/ │ ├── Model/ # 数据模型层 │ ├── Gender.cs # 枚举性别 │ ├── People.cs # 抽象类公共属性 │ ├── Boy.cs # 男孩类继承 People │ └── Girl.cs # 女孩类继承 People │ ├── DAL/ # 数据访问层 │ ├── IDal.cs # 泛型接口定义 CRUD 契约 │ └── Dal.cs # 泛型类实现 CRUD │ ├── Manager/ # 业务管理层 │ └── StudentManager.cs # 管理器管理 Boy/Girl 的 Dal │ └── Program.cs # UI 层主程序入口6. 核心机制速查表模块类/接口核心功能关键代码ModelPeople定义公共属性protected People(...)ModelBoy男生特有属性: base(..., Gender.Male, ...)ModelGirl女生特有属性: base(..., Gender.Female, ...)DALIDal数据访问契约void Add(T item)DALDal数据存储实现_list.Any(p p.Name name)ManagerStudentManager获取对应 Dalreturn (IDal)_boyDalProgramRunSubMenu通用子菜单where T : PeopleProgramAdd添加学生(T)(object)new Boy(...)

相关新闻

最新新闻

亲测AI床垫,睡眠真的变好了吗?

亲测AI床垫,睡眠真的变好了吗?

智能床垫选购体验:一个普通用户的真实分享声明:本文为个人消费体验分享。文中提及的产品体验均基于个人使用感受,不构成专业建议。本产品为智能家居用品,非医疗器械。兄弟集美们,今天聊个实在的。最近老有人问我&#…

2026/8/9 5:05:44
UE4逆向实战:定位GObjects与Hook PostRender实现游戏内部绘制

UE4逆向实战:定位GObjects与Hook PostRender实现游戏内部绘制

1. 项目概述:为什么我们要深挖GObjects与PostRender 如果你正在研究UE4游戏的逆向,无论是为了安全分析、外挂检测,还是纯粹的技术探索,那么“GObjects”和“PostRender”这两个词对你来说一定不陌生。它们就像是UE4引擎内部世界的…

2026/8/9 5:05:44
炸裂!SpaceX 600 亿收购 Cursor,编程独角兽品牌将逐步淘汰,AI 格局生变?

炸裂!SpaceX 600 亿收购 Cursor,编程独角兽品牌将逐步淘汰,AI 格局生变?

据 The Information 爆料,SpaceX 拟 600 亿美元收购 AI 编程独角兽 Cursor,最快下周五完成交易。Cursor 品牌将逐步淘汰,公司也将被拆分并入 SpaceXAI。 天价收购,品牌消逝 这 600 亿美元是史上最大的初创公司收购案。交易最迟 8 …

2026/8/9 5:05:44
级联H桥SVG在电网不平衡下的控制策略优化

级联H桥SVG在电网不平衡下的控制策略优化

1. 级联H桥SVG在电网不平衡场景下的核心挑战 电力系统中,三相电压不平衡是配电网络最常见的电能质量问题之一。当电网出现电压幅值不对称或相位偏差时,传统静止无功发生器(SVG)的控制策略会面临三个关键挑战: 负序电流…

2026/8/9 5:05:44
Node.js REPL交互式开发环境深度解析与实战

Node.js REPL交互式开发环境深度解析与实战

1. Node.js REPL:开发者的交互式游乐场当你在终端输入node命令时,那个带着>符号的神秘界面就是Node.js的REPL(Read-Eval-Print Loop)环境。这个看似简单的交互式解释器,实际上是每个Node.js开发者都应该熟练掌握的瑞…

2026/8/9 5:05:43
2026最权威学生党论文工具榜单:便宜好用不踩坑,这些神器被学长学姐悄悄收藏

2026最权威学生党论文工具榜单:便宜好用不踩坑,这些神器被学长学姐悄悄收藏

宝子们,是不是一到毕业季就感觉头秃?😫 论文查重贵到肉疼、降重改到怀疑人生、开题报告格式改到崩溃……作为过来人,我太懂这种“预算有限但又啥都得用”的痛了!别慌,今天这篇榜单就是专门给你们这些学生党…

2026/8/9 4:55:27