採用面向接口編程,分離數據模型、業務邏輯與存儲:
IStudent:學生屬性契約IStudentIMP:業務操作契約 (增刪改查、存檔)Student:實體類,實現 IStudentStudentIMP:業務實現,內部用 Hashtable 索引
public interface IStudent
{
string ID { get; set; }
string Name { get; set; }
string Gender { get; set; }
string ClassNum { get; set; }
string Specialty { get; set; }
string BDay { get; set; } // 建議改為 DateTime
}
public interface IStudentIMP
{
void AddInfo();
void DisplayInfo();
void DropInfo();
void SaveFile();
int SearchInfo(string id); // 返回哈希碼判斷是否存在
void ModifyInfo(); // 原文接口缺失,實現類有此方法
}
class Student : IStudent
{
private string _id, _name, _gender, _classNum, _specialty;
private DateTime _bday;
public string ID { get => _id; set => _id = value; }
public string Name { get => _name; set => _name = value; }
public string Gender { get => _gender; set => _gender = value; }
public string ClassNum { get => _classNum; set => _classNum = value; }
public string Specialty { get => _specialty; set => _specialty = value; }
public string BDay
{
get => _bday.ToShortDateString();
set => _bday = DateTime.Parse(value); // 可能拋異常,建議 TryParse
}
public Student(string id, string name, string gender, string classNum, string specialty, string bday)
{
ID = id; Name = name; Gender = gender; ClassNum = classNum; Specialty = specialty; BDay = bday;
}
}
class StudentIMP : IStudentIMP
{
private Hashtable _students = new Hashtable(); // key: ID, value: Student
// 索引器:按 ID 快速查找
public Student this[string id]
{
get => _students.ContainsKey(id) ? (Student)_students[id] : null;
}
public void AddInfo()
{
// 控制台交互輸入各字段...
Student s = new Student(id, name, gender, classNum, specialty, bday);
_students.Add(s.ID, s); // ID 重複會拋異常,建議先 ContainsKey 判斷
}
public int SearchInfo(string id)
{
return _students.ContainsKey(id) && _students[id] is Student st && st.ID == id
? st.GetHashCode() : "20051120000".GetHashCode(); // 魔術數字作為「未找到」標記
}
public void SaveFile()
{
// StreamWriter 寫入制表符對齊文本文件
// 格式:ID Name Gender Class Specialty Birthday
}
public void DisplayInfo() { /* 遍歷 Hashtable 打印 */ }
public void DropInfo() { /* 檢查存在 -> 確認 -> Remove */ }
public void ModifyInfo() { /* 顯示菜單 -> 選擇字段 -> 更新 */ }
}
[STAThread]
static void Main()
{
Console.Title = "Student IMP - by 88250";
Console.ForegroundColor = ConsoleColor.DarkGreen;
StudentIMP sys = new StudentIMP();
string input;
do
{
Console.Clear();
ShowMenu();
input = Console.ReadLine();
switch (input)
{
case "1": sys.AddInfo(); break;
case "2": sys.ModifyInfo(); break;
case "3": sys.DropInfo(); break;
case "4": sys.SaveFile(); break;
case "5": sys.DisplayInfo(); break;
case "6": ShowHelp(); break;
case "7": return;
default: Console.WriteLine("功能未定義!"); break;
}
Console.WriteLine("按任意鍵繼續...");
Console.ReadLine();
} while (true);
}
| 問題 | 建議 |
|---|---|
| Hashtable 非泛型 | 改用 Dictionary<string, Student>,類型安全、性能更好 |
| BDay 用 string 存儲 | 屬性類型改為 DateTime,UI 輸出時再格式化 |
| SearchInfo 返回哈希碼 | 語義不清,改為 bool TryGetStudent(id, out Student) 或返回 Student? |
| 魔術字符串 "20051120000" | 定義常量 const string NOT_FOUND_KEY = "NOT_FOUND"; |
| 控制台輸入無驗證 | 添加長度、格式、唯一性校驗;生日用 DateTime.TryParse |
| 文件存儲為純文本 | 改用 JSON (System.Text.Json) 或 SQLite,便於後續擴展 |
| 異常處理缺失 | 關鍵操作 (文件 IO、Parse) 包裹 try-catch,友好提示 |
| 單文件耦合 | 分層:Models、Services、UI、DataAccess |
Spectre.Console 構建豐富 TUI(表格、進度條、提示)Entity Framework Core + SQLite 替換手寫文件存儲Microsoft.Extensions.DependencyInjection) 解耦接口實現這是一個典型的「教學級」控制台管理系統,展示了接口隔離、集合索引、文件持久化、菜單驅動循環等基礎編程模式。代碼結構清晰,但使用了較老舊的非泛型集合與魔術值。對初學者理解面向對象設計、集合應用、文件 IO 有很好的參考價值;實戰項目請參考改進建議重構。