设计一个学生管理系统:
- 类图

-
涉及知识点:
- 面向对象基础(
封装:Getter、Setter
继承:显式实现是接口、隐式实现接口、base、this、方法的重载和重写
多态:虚方法
) - 几个类似指针的东西:ref、out、params、delegate
- 文件操作
- 几个常用接口:IComparable IComparer
- 常用数据结构:List、Dictionary
- 匿名内部类、lamba表达式、LINQ
- 重载运算符
- 面向对象基础(
-
需求分析:
- 能过实现增删改查(查询使用委托+Lambda+LINQ)
- 数据持久化(文件操作)
- 排序功能实现(IComparable IComparer)
-
收获:
-
Getter和Setter的用法:
把方法直接看成变量来使用例如给student.id赋值student.id = 1打印student.idConsole.WriteLine(student.id)
Getter、Setter必须紧跟在变量名后 -
Getter和Setter会给默认实现:
protected int id { get; set; } ===> public int id { get { return this.id; } set { id = value; } } -
重写方法必须要加上override关键字
public override string ToString() { return this.id + " " + this.name + " " + this.age; } -
重写Equals方法要注意
首先使用as关键字进行类型转化,as比强转更安全,如果不能强转会返回null
其次记得加上override
最后return判断条件 -
C#没有super关键字,继承父类的构造方法使用base
public Student(int id, string name, int age) : base(id, name, age) { } -
运算符重载
public static Student operator +(Student a, Student b) { Student s = new Student(); s.Id = a.Id + b.Id; s.Age = a.Age + b.Age; return s; } -
析构函数不能用public修饰~StudentManager()
-
委托其实就是函数指针,使用方式:
声明一个函数指针指向一个对应的函数Select select = DelegateUtils.SelectSample;通过这个函数指针调用指向的函数
select(students, id); -
ref和out相当于指针标志*,但区别在于out类型必须在函数中强制赋值,不然会报错。例如这两个函数:
public bool Delete(int id, out Student student) { student = SelectById(id); if(student == null) { Console.WriteLine("查无此人"); return false; } students.Remove(student); return true; } public bool Update(ref Student student, string name, int age) { student.name = name; student.age = age; return true; } -
文件操作使用FileInfo获取文件的信息,使用StreamReader和StreamWriter进行IO操作
public void Load() { string path = @"../../../student.txt"; FileInfo fileInfo = new FileInfo(path); if (!fileInfo.Exists) fileInfo.Create().Close();//创建文件。Close()关闭流并释放与之关联的所有资源 StreamReader reader = new StreamReader(path); while (reader.Peek() != -1)//判断文件中是否有字符 { string str = reader.ReadLine(); string[] infos = str.Split(" "); Student student = new Student(Convert.ToInt32(infos[0]), infos[1], Convert.ToInt32(infos[2])); students.Add(student); } reader.Close(); } public void Store() { string path = @"../../../student.txt"; FileInfo fileInfo = new FileInfo(path); if (!fileInfo.Exists) fileInfo.Create().Close();//创建文件。Close()关闭流并释放与之关联的所有资源 StreamWriter writer = new StreamWriter(path); foreach(Student student in students) { writer.WriteLine(student.ToString()); writer.Flush();//刷新缓存 } writer.Close(); } -
Action委托是一个没有返回值的委托,<>中可以声明传入参数的个数类型
-
Lambda表达式和Java中一样只不过使用=> 来表示,而且Lambda表达式只能用于委托类型
public static Student SelectLambda(List<Student> students, int id) { Student ans = null; Action<int> action = new Action<int>((int id) => { foreach (Student student in students) { if (student.id == id) { ans = student; break; } } }); action(id); return ans; } -
LINQ类似于数据库的SQL语句均由三部分构成:
- 获取数据源
- 建立查询表达式
- 执行查询var temp = from student in students //建立结果集 where student.id == id //查询条件 select student; //执行查询
-
-
源代码
using System;
using System.Collections.Generic;
using System.Text;
namespace StudentLib.src
{
//抽象类 人
//其实这个类没必要只不过想涉及到继承的知识点
abstract class Person
{
//Getter和Setter紧跟在属性后面
public int id { get; set; }
public string name { get; set; }
public int age { get; set; }
public Person(){}
public Person(int id, string name, int age)
{
this.id = id;
this.name = name;
this.age = age;
}
//重载时注意要有override关键字
public override string ToString()
{
return this.id + " " + this.name + " " + this.age;
}
public override bool Equals(object obj)
{
Person p = obj as Person;
return this.id == p.id;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace StudentLib.src
{
//学生类
//继承采用冒号:,多继承用逗号分割
class Student : Person, IComparable
{
public Student() { }
//使用base调用父类的构造函数
public Student(int id, string name, int age) : base(id, name, age) { }
public int CompareTo(object obj)
{
Student student = obj as Student;
return this.id - student.id;
}
//使用operator来重载运算符
public static Student operator +(Student a, Student b)
{
Student s = new Student();
s.id = a.id + b.id;
s.age = a.age + b.age;
return s;
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace StudentLib.src
{
//学生管理类
class StudentManager
{
//声明委托
public delegate Student Select(List<Student> students, int id);
//用于存储学生的集合
List<Student> students = new List<Student>();
//构造函数,调用构造函数时从文件中读取数据初始信息
public StudentManager()
{
Load();
}
//增
public bool Insert(Student student)
{
students.Add(student);
return true;
}
//删 这里是为了使用out的知识点所以参数上声明了一个out
public bool Delete(int id, out Student student)
{
student = SelectById2(id,DelegateUtils.SelectSample);
if(student == null)
{
Console.WriteLine("查无此人");
return false;
}
students.Remove(student);
return true;
}
//改 这里是为了使用ref的知识所以参数上使用了一个ref
public bool Update(ref Student student, string name, int age)
{
student.name = name;
student.age = age;
return true;
}
//查 这里是为了使用委托所以查询采用委托的方式获取
public Student SelectById(int id)
{
// Select select = DelegateUtils.SelectSample;
// Select select = DelegateUtils.SelectLambda;
Select select = DelegateUtils.SelectLINQ; // 声明委托变量并指向目标函数
//调用委托函数
return select(students, id);
}
//查 这里将委托作为参数传入
public Student SelectById2(int id, Select select)
{
//调用委托函数
return select(students, id);
}
//根据id进行排序,是让Student实现IComparable的CompareTo方法
public void SortById()
{
students.Sort();
}
//根据age排序,是new一个比较器的方式实现,通过StudentCompater实现IComparer的Compare方法
public void SortByAge(IComparer<Student> comparer)
{
students.Sort(comparer);
}
//遍历
public void Show()
{
foreach(Student student in students)
{
Console.WriteLine(student);
}
}
//从文件中加载数据
public void Load()
{
string path = @"../../../student.txt";
FileInfo fileInfo = new FileInfo(path);
if (!fileInfo.Exists)
fileInfo.Create().Close();//创建文件。Close()关闭流并释放与之关联的所有资源
StreamReader reader = new StreamReader(path);
while (reader.Peek() != -1)//判断文件中是否有字符
{
string str = reader.ReadLine();
string[] infos = str.Split(" ");
Student student = new Student(Convert.ToInt32(infos[0]), infos[1], Convert.ToInt32(infos[2]));
students.Add(student);
}
reader.Close();
}
//数据持久化 将内存中的数据存到磁盘
public void Store()
{
string path = @"../../../student.txt";
FileInfo fileInfo = new FileInfo(path);
if (!fileInfo.Exists)
fileInfo.Create().Close();//创建文件。Close()关闭流并释放与之关联的所有资源
StreamWriter writer = new StreamWriter(path);
foreach(Student student in students)
{
writer.WriteLine(student.ToString());
writer.Flush();//刷新缓存
}
writer.Close();
}
}
}
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;
namespace StudentLib.src
{
//比较器
class StudentCompater : IComparer<Student>
{
public int Compare([AllowNull] Student x, [AllowNull] Student y)
{
return x.age - y.age;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace StudentLib.src
{
//实现委托的工具类
class DelegateUtils
{
//简单的查询
public static Student SelectSample(List<Student> students, int id)
{
foreach (Student student in students)
{
if (student.id == id) return student;
}
return null;
}
//通过Action和Lambda表达式查询
public static Student SelectLambda(List<Student> students, int id)
{
Student ans = null;
Action<int> action = new Action<int>((int id) => {
foreach (Student student in students)
{
if (student.id == id)
{
ans = student;
break;
}
}
});
action(id);
return ans;
}
//通过LINQ查询
public static Student SelectLINQ(List<Student> students, int id)
{
var temp = from student in students //建立结果集
where student.id == id //查询条件
select student; //执行查询
foreach (Student student1 in temp)
{
return student1;
}
return null;
}
}
}
using System;
using System.Collections.Generic;
using StudentLib.src;
namespace StudentLib
{
class Program
{
static void Main(string[] args)
{
StudentManager manager = new StudentManager();
int bottom = 1;
while (bottom != 0)
{
int index = 0;
Console.WriteLine("=========欢迎来到学生管理系统========");
Console.WriteLine($"{index++}. 退出学生管理系统");
Console.WriteLine($"{index++}. 添加学生");
Console.WriteLine($"{index++}. 删除一个学生");
Console.WriteLine($"{index++}. 修改一个学生信息");
Console.WriteLine($"{index++}. 查询一个学生信息");
Console.WriteLine($"{index++}. 展示学生信息");
Console.WriteLine($"{index++}. 根据id给学生信息排序");
Console.WriteLine($"{index++}. 根据age给学生信息排序");
Console.WriteLine($"{index++}. 保存学生信息");
Console.WriteLine("请输入您的指令");
bottom = Convert.ToInt32(Console.ReadLine());
switch (bottom)
{
case 0:
Environment.Exit(0);
break;
case 1:
manager.Insert(new Student(new Random().Next(), "张三", new Random().Next()));
break;
case 2:
Console.WriteLine("请输入要删除的学生id");
int id = Convert.ToInt32(Console.ReadLine());
Student student = new Student();
manager.Delete(id, out student);
Console.WriteLine(student);
break;
case 3:
Console.WriteLine("请输入要修改的学生id");
id = Convert.ToInt32(Console.ReadLine());
student = manager.SelectById2(id,DelegateUtils.SelectLambda);
Console.WriteLine("请输入要修改的学生姓名");
string name = Console.ReadLine();
Console.WriteLine("请输入要修改的学生年龄");
int age = Convert.ToInt32(Console.ReadLine());
manager.Update(ref student, name, age);
Console.WriteLine(student);
break;
case 4:
Console.WriteLine("请输入要查询的学生id");
id = Convert.ToInt32(Console.ReadLine());
student = manager.SelectById(id);
Console.WriteLine(student);
break;
case 5:
manager.Show();
break;
case 6:
manager.SortById();
break;
case 7:
manager.SortByAge(new StudentCompater());
break;
case 8:
manager.Store();
break;
}
}
}
}
}

被折叠的 条评论
为什么被折叠?



