news 2026/8/9 3:55:20

【C# 泛型接口与抽象类实战 —— 学生管理系统核心知识点总结】

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【C# 泛型接口与抽象类实战 —— 学生管理系统核心知识点总结】

项目涉及知识点

知识点说明
泛型类Dal实现数据存储与增删改查
泛型接口IDal定义数据访问契约
泛型约束where T : People限制类型必须继承自People
抽象类People定义公共属性与行为模板
继承BoyGirl继承自People
枚举Gender定义性别常量
构造函数基类受保护构造 + 子类构造调用base()
方法重写ToString()重写实现自定义输出
Lambda 表达式p => p.Name == item.Name简化集合操作
LINQ 方法Any()FirstOrDefault()ToArray()
多态接口引用指向实现类对象
访问修饰符protected setprotected构造
异常处理throw主动抛出业务异常
类型判断与转换typeof(T)+(T)(object)强制转换

1. 枚举(Enum)

csharp

public enum Gender { Male = 1, Female = 2 }

2. 抽象基类People(抽象类 + 受保护构造 + 虚方法重写)

csharp

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}分"; } }

3. 子类Boy/Girl(继承 +base()调用父类构造)

csharp

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) // 固定性别为男 { // 父类构造已完成赋值 } } 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 IDal<T> where T : People { void Add(T item); bool Remove(string name); // 按名字删除 void Update(string name, T newValue); T FindOne(string name); IEnumerable<T> GetAll(); }

5. 泛型实现类Dal(泛型类 + Lambda + LINQ)

csharp

public class Dal<T> : IDal<T> where T : People { private readonly List<T> _list = new List<T>(); // 添加(使用 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 IEnumerable<T> 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(多态 + 类型判断)

csharp

public class StudentManager { // 多态:父接口引用指向子类对象 private readonly IDal<Boy> _boyDal = new Dal<Boy>(); private readonly IDal<Girl> _girlDal = new Dal<Girl>(); public StudentManager() { // 默认初始化两条数据 _boyDal.Add(new Boy("张三", 18, 88.5)); _girlDal.Add(new Girl("小雨", 28, 100)); } // 根据类型返回对应的 Dal public IDal<T> GetDal<T>() where T : People { if (typeof(T) == typeof(Boy)) return (IDal<T>)_boyDal; if (typeof(T) == typeof(Girl)) return (IDal<T>)_girlDal; throw new NotSupportedException("不支持的类型"); } }

7. Program 主程序(类型转换 + 泛型方法调用)

csharp

internal class Program { private static readonly StudentManager _mgr = new StudentManager(); static void Main(string[] args) { // 选择男生或女生 switch (Console.ReadLine()) { case "1": RunSubMenu<Boy>(); break; case "2": RunSubMenu<Girl>(); break; case "0": return; } } private static void RunSubMenu<T>() where T : People { var dal = _mgr.GetDal<T>(); // 获取对应类型的 Dal // 循环显示菜单,调用 Add/Remove/Update/Query } // 添加(类型判断 + 强制转换) private static void Add<T>(IDal<T> 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).Name

9. 类图关系(简化)

text

┌─────────────────┐ │ <<interface>> │ │ IDal<T> │ │ +Add() │ │ +Remove() │ │ +Update() │ │ +FindOne() │ │ +GetAll() │ └────────┬────────┘ │ 实现 ▼ ┌─────────────────┐ ┌─────────────────┐ │ Dal<T> │────────│ 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.cs

csharp

namespace _1.学生管理系统.Model { public enum Gender { Male = 1, Female = 2 } }

1.2 People 抽象类 ——Model/People.cs

csharp

using 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.cs

csharp

namespace _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.cs

csharp

namespace _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.cs

csharp

using _1.学生管理系统.Model; namespace _1.学生管理系统.DAL { // 泛型接口,约束 T 必须是 People 或其派生类 public interface IDal<T> where T : People { void Add(T item); bool Remove(string name); void Update(string name, T newValue); T FindOne(string name); IEnumerable<T> GetAll(); } }

2.2 Dal 泛型实现类 ——DAL/Dal.cs

csharp

using _1.学生管理系统.Model; namespace _1.学生管理系统.DAL { public class Dal<T> : IDal<T> where T : People { private readonly List<T> _list = new List<T>(); // ===== 添加模块 ===== 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 IEnumerable<T> 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.cs

csharp

using _1.学生管理系统.DAL; using _1.学生管理系统.Model; namespace _1.学生管理系统.Manager { public class StudentManager { // 多态:父接口引用指向子类对象 private readonly IDal<Boy> _boyDal = new Dal<Boy>(); private readonly IDal<Girl> _girlDal = new Dal<Girl>(); // ===== 构造函数:初始化默认数据 ===== public StudentManager() { _boyDal.Add(new Boy("张三", 18, 88.5)); _girlDal.Add(new Girl("小雨", 28, 100)); } // ===== 获取 Dal 模块 ===== public IDal<T> GetDal<T>() where T : People { if (typeof(T) == typeof(Boy)) return (IDal<T>)_boyDal; if (typeof(T) == typeof(Girl)) return (IDal<T>)_girlDal; throw new NotSupportedException("不支持的类型,必须是People的派生"); } } }

4. Program 主程序(UI 层)

4.1 Program 类 ——Program.cs

csharp

using _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": RunSubMenu<Boy>(); break; case "2": RunSubMenu<Girl>(); break; case "0": return; default: break; } } // ===== 子菜单模块(通用,T 可以是 Boy 或 Girl) ===== private static void RunSubMenu<T>() where T : People { var dal = _mgr.GetDal<T>(); 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 Add<T>(IDal<T> 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 Remove<T>(IDal<T> dal) where T : People { Console.Write("请输入要删除的名字:"); var ok = dal.Remove(Console.ReadLine()); Console.WriteLine(ok ? "删除成功" : "未找到"); Console.ReadKey(); } // ===== 修改模块 ===== private static void Update<T>(IDal<T> 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 Query<T>(IDal<T> 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)_boyDal
ProgramRunSubMenu通用子菜单where T : People
ProgramAdd添加学生(T)(object)new Boy(...)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/9 3:50:41

AutoCAD许可证管理优化与效率提升方案

1. AutoCAD许可证管理的现状与挑战在工程设计领域&#xff0c;AutoCAD作为行业标准软件&#xff0c;其许可证管理一直是企业IT部门头疼的问题。根据行业调研数据&#xff0c;超过76%的企业存在许可证分配不合理的情况&#xff0c;而平均闲置率更是高达30-45%。这意味着每10个购…

作者头像 李华
网站建设 2026/8/9 3:49:12

云原生AI Agent实战:OpenClaw与飞书CLI构建企业级智能助手

1. 项目概述&#xff1a;当云原生AI基建遇上企业级协同最近在折腾AI Agent的落地&#xff0c;发现了一个挺有意思的“王炸组合”&#xff1a;腾讯云的OpenClaw和飞书的CLI工具。这俩东西单拿出来&#xff0c;一个是云原生AI应用框架&#xff0c;一个是企业协同平台的命令行接口…

作者头像 李华
网站建设 2026/8/9 3:47:11

面向参赛备赛群体 南京智升学教育2026南京奥数竞赛备考白皮书

面向参赛备赛群体 南京智升学教育2026南京奥数竞赛备考白皮书本白皮书由南京智升学教育结合十年南京本地培优服务经验编撰&#xff0c;所有内容均基于南京鼓楼区、玄武区、秦淮区、建邺区、雨花台区、江北新区、江宁区近三年参赛学员的真实学习数据整理&#xff0c;无夸大表述&…

作者头像 李华
网站建设 2026/8/9 3:46:16

Qwen-Image-3.0商用版发布:降低视觉AI集成门槛的实战指南

如果你最近在关注多模态大模型&#xff0c;特别是需要处理图像、文档、图表等视觉信息的场景&#xff0c;那么今天要聊的Qwen-Image-3.0正式商用&#xff0c;绝对是一个值得你停下手里工作&#xff0c;花十分钟仔细了解的关键节点。这不仅仅是一个“又一个大模型发布了”的新闻…

作者头像 李华
网站建设 2026/8/9 3:45:53

ComfyUI 2026保姆级安装指南:从零部署到高效AI绘画

还在为 Stable Diffusion WebUI 的复杂操作和资源占用而烦恼&#xff1f;想体验更高效、更稳定、更符合工作流思维的 AI 绘图方式吗&#xff1f;ComfyUI 作为一款基于节点式工作流的 Stable Diffusion 图形界面&#xff0c;正以其卓越的性能、清晰的逻辑和强大的可定制性&#…

作者头像 李华
网站建设 2026/8/9 3:45:13

分类流映射(CFMs)大规模扩展:从理论到工程实践

在机器学习领域&#xff0c;生成模型的核心任务之一是从简单分布&#xff08;如高斯噪声&#xff09;中采样&#xff0c;并将其转化为复杂的数据分布&#xff08;如图像、文本&#xff09;。近年来&#xff0c;扩散模型凭借其强大的生成能力成为主流&#xff0c;但其迭代去噪过…

作者头像 李华