C# 完全学习指南C# 完全学习指南
首页
基础教程
进阶内容
实战项目
编程指南
首页
基础教程
进阶内容
实战项目
编程指南
  • 实战项目

    • 🎨 实战项目
    • 项目1 - 控制台计算器
    • 项目2 - 待办事项管理
    • 项目3 - 学生信息管理系统
    • 项目4 - 命令行文件管理器
    • 项目5 - Web API 接口开发

项目2 - 待办事项管理

嗨,朋友!我是长安。

完成了计算器项目,这次我们要做一个待办事项管理应用,学习如何使用集合管理数据,并实现数据的持久化存储。这个项目会帮你掌握面向对象编程、集合操作和文件读写。

🎯 项目需求

功能列表

  1. 添加待办事项
  2. 查看所有待办事项(区分已完成和未完成)
  3. 标记待办事项为完成
  4. 删除待办事项
  5. 保存到文件/从文件加载
  6. 退出程序

运行效果

===== 待办事项管理 =====
1. 添加事项
2. 查看所有事项
3. 标记完成
4. 删除事项
5. 保存并退出
请选择操作: 1

请输入待办事项: 学习 C# 面向对象编程
✓ 添加成功!

请选择操作: 2

===== 待办事项列表 =====
[ ] 1. 学习 C# 面向对象编程
===========================

🤔 需求分析

在开始写代码之前,我们先分析一下需要做什么:

  1. 数据管理

    • 定义待办事项的数据结构
    • 使用集合存储多个待办事项
    • 支持增删改查操作
  2. 用户交互

    • 显示菜单供用户选择
    • 接收用户输入并执行相应操作
    • 提供友好的操作反馈
  3. 数据持久化

    • 将数据保存到文件
    • 程序启动时从文件加载数据
    • 确保数据不丢失
  4. 异常处理

    • 处理无效输入
    • 处理文件读写异常

📐 功能设计

1. 程序流程图

开始
  ↓
从文件加载数据
  ↓
┌─────────────┐
│ 显示菜单     │←────┐
└─────────────┘     │
  ↓                 │
获取用户选择        │
  ↓                 │
┌─────────────┐     │
│ 1.添加事项  │─────┤
│ 2.查看事项  │─────┤
│ 3.标记完成  │─────┤
│ 4.删除事项  │─────┤
│ 5.保存退出  │─────┘
└─────────────┘
  ↓
保存数据到文件
  ↓
结束

2. 类设计

TodoItem 类 - 表示单个待办事项

  • 属性:Id、内容、是否完成、创建时间

TodoManager 类 - 管理所有待办事项

  • 方法:添加、删除、标记完成、查看、保存、加载

💻 代码实现

第一步:创建项目

# 创建新的控制台项目
mkdir TodoListApp
cd TodoListApp
dotnet new console

第二步:定义 TodoItem 类

首先,我们需要定义待办事项的数据结构:

using System;

namespace TodoListApp
{
    /// <summary>
    /// 待办事项类
    /// </summary>
    public class TodoItem
    {
        // 唯一标识符
        public int Id { get; set; }
        
        // 事项内容
        public string Content { get; set; }
        
        // 是否完成
        public bool IsCompleted { get; set; }
        
        // 创建时间
        public DateTime CreatedTime { get; set; }
        
        // 构造函数
        public TodoItem(int id, string content)
        {
            Id = id;
            Content = content;
            IsCompleted = false;
            CreatedTime = DateTime.Now;
        }
        
        // 重载 ToString 方法,方便显示
        public override string ToString()
        {
            string status = IsCompleted ? "✓" : " ";
            return $"[{status}] {Id}. {Content}";
        }
    }
}

代码讲解:

  • Id:每个待办事项的唯一编号,便于查找和操作
  • Content:事项的具体内容
  • IsCompleted:标记事项是否已完成,默认为 false
  • CreatedTime:记录创建时间,可用于排序
  • ToString():重写该方法,让对象显示时更友好

第三步:创建 TodoManager 管理类

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace TodoListApp
{
    /// <summary>
    /// 待办事项管理类
    /// </summary>
    public class TodoManager
    {
        private List<TodoItem> todoItems;  // 存储所有待办事项
        private int nextId;                 // 下一个可用的 ID
        private readonly string filePath;   // 数据文件路径
        
        // 构造函数
        public TodoManager(string filePath = "todos.txt")
        {
            this.filePath = filePath;
            todoItems = new List<TodoItem>();
            nextId = 1;
            LoadFromFile();
        }
        
        /// <summary>
        /// 添加待办事项
        /// </summary>
        public void AddTodo(string content)
        {
            if (string.IsNullOrWhiteSpace(content))
            {
                Console.WriteLine("✗ 内容不能为空!");
                return;
            }
            
            var todo = new TodoItem(nextId++, content);
            todoItems.Add(todo);
            Console.WriteLine("✓ 添加成功!");
        }
        
        /// <summary>
        /// 显示所有待办事项
        /// </summary>
        public void ShowAll()
        {
            Console.WriteLine("\n===== 待办事项列表 =====");
            
            if (todoItems.Count == 0)
            {
                Console.WriteLine("暂无待办事项");
            }
            else
            {
                // 按完成状态分组显示
                var uncompletedItems = todoItems.Where(t => !t.IsCompleted).ToList();
                var completedItems = todoItems.Where(t => t.IsCompleted).ToList();
                
                if (uncompletedItems.Count > 0)
                {
                    Console.WriteLine("\n未完成:");
                    foreach (var item in uncompletedItems)
                    {
                        Console.WriteLine(item);
                    }
                }
                
                if (completedItems.Count > 0)
                {
                    Console.WriteLine("\n已完成:");
                    Console.ForegroundColor = ConsoleColor.Gray;
                    foreach (var item in completedItems)
                    {
                        Console.WriteLine(item);
                    }
                    Console.ResetColor();
                }
            }
            
            Console.WriteLine("===========================");
        }
        
        /// <summary>
        /// 标记待办事项为完成
        /// </summary>
        public void MarkAsCompleted(int id)
        {
            var todo = todoItems.FirstOrDefault(t => t.Id == id);
            
            if (todo == null)
            {
                Console.WriteLine("✗ 找不到该事项!");
                return;
            }
            
            if (todo.IsCompleted)
            {
                Console.WriteLine("该事项已经完成了!");
                return;
            }
            
            todo.IsCompleted = true;
            Console.WriteLine("✓ 已标记为完成!");
        }
        
        /// <summary>
        /// 删除待办事项
        /// </summary>
        public void DeleteTodo(int id)
        {
            var todo = todoItems.FirstOrDefault(t => t.Id == id);
            
            if (todo == null)
            {
                Console.WriteLine("✗ 找不到该事项!");
                return;
            }
            
            todoItems.Remove(todo);
            Console.WriteLine("✓ 删除成功!");
        }
        
        /// <summary>
        /// 保存到文件
        /// </summary>
        public void SaveToFile()
        {
            try
            {
                using (StreamWriter writer = new StreamWriter(filePath))
                {
                    // 保存下一个可用的 ID
                    writer.WriteLine(nextId);
                    
                    // 保存每个待办事项
                    foreach (var item in todoItems)
                    {
                        string line = $"{item.Id}|{item.Content}|{item.IsCompleted}|{item.CreatedTime}";
                        writer.WriteLine(line);
                    }
                }
                
                Console.WriteLine("\n✓ 数据已保存!");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"\n✗ 保存失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 从文件加载
        /// </summary>
        private void LoadFromFile()
        {
            if (!File.Exists(filePath))
            {
                return;
            }
            
            try
            {
                using (StreamReader reader = new StreamReader(filePath))
                {
                    // 读取下一个可用的 ID
                    string firstLine = reader.ReadLine();
                    if (!string.IsNullOrEmpty(firstLine))
                    {
                        nextId = int.Parse(firstLine);
                    }
                    
                    // 读取每个待办事项
                    string line;
                    while ((line = reader.ReadLine()) != null)
                    {
                        string[] parts = line.Split('|');
                        if (parts.Length == 4)
                        {
                            var item = new TodoItem(int.Parse(parts[0]), parts[1])
                            {
                                IsCompleted = bool.Parse(parts[2]),
                                CreatedTime = DateTime.Parse(parts[3])
                            };
                            todoItems.Add(item);
                        }
                    }
                }
                
                Console.WriteLine($"✓ 已加载 {todoItems.Count} 条待办事项");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ 加载失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 获取统计信息
        /// </summary>
        public void ShowStatistics()
        {
            int total = todoItems.Count;
            int completed = todoItems.Count(t => t.IsCompleted);
            int uncompleted = total - completed;
            double completionRate = total > 0 ? (double)completed / total * 100 : 0;
            
            Console.WriteLine("\n===== 统计信息 =====");
            Console.WriteLine($"总数: {total}");
            Console.WriteLine($"已完成: {completed}");
            Console.WriteLine($"未完成: {uncompleted}");
            Console.WriteLine($"完成率: {completionRate:F1}%");
            Console.WriteLine("====================");
        }
    }
}

代码讲解:

  • List<TodoItem>:使用泛型集合存储所有待办事项
  • LINQ:使用 FirstOrDefault、Where、Count 等方法查询数据
  • StreamWriter/StreamReader:用于文件的读写操作
  • 数据格式:使用 | 分隔符将对象的属性保存为一行文本

第四步:实现主程序

using System;

namespace TodoListApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("===== 待办事项管理系统 =====");
            Console.WriteLine("欢迎使用!\n");
            
            TodoManager manager = new TodoManager();
            
            bool running = true;
            while (running)
            {
                ShowMenu();
                
                string choice = Console.ReadLine();
                Console.WriteLine();
                
                switch (choice)
                {
                    case "1":
                        AddTodo(manager);
                        break;
                    case "2":
                        manager.ShowAll();
                        break;
                    case "3":
                        MarkCompleted(manager);
                        break;
                    case "4":
                        DeleteTodo(manager);
                        break;
                    case "5":
                        manager.ShowStatistics();
                        break;
                    case "6":
                        manager.SaveToFile();
                        running = false;
                        break;
                    default:
                        Console.WriteLine("✗ 无效的选项,请重新选择!");
                        break;
                }
                
                if (running)
                {
                    Console.WriteLine("\n按任意键继续...");
                    Console.ReadKey();
                    Console.Clear();
                }
            }
            
            Console.WriteLine("\n感谢使用!再见!\n");
        }
        
        /// <summary>
        /// 显示菜单
        /// </summary>
        static void ShowMenu()
        {
            Console.WriteLine("\n===== 待办事项管理 =====");
            Console.WriteLine("1. 添加事项");
            Console.WriteLine("2. 查看所有事项");
            Console.WriteLine("3. 标记完成");
            Console.WriteLine("4. 删除事项");
            Console.WriteLine("5. 统计信息");
            Console.WriteLine("6. 保存并退出");
            Console.WriteLine("========================");
            Console.Write("请选择操作: ");
        }
        
        /// <summary>
        /// 添加待办事项
        /// </summary>
        static void AddTodo(TodoManager manager)
        {
            Console.Write("请输入待办事项: ");
            string content = Console.ReadLine();
            manager.AddTodo(content);
        }
        
        /// <summary>
        /// 标记完成
        /// </summary>
        static void MarkCompleted(TodoManager manager)
        {
            Console.Write("请输入要标记的事项编号: ");
            if (int.TryParse(Console.ReadLine(), out int id))
            {
                manager.MarkAsCompleted(id);
            }
            else
            {
                Console.WriteLine("✗ 请输入有效的编号!");
            }
        }
        
        /// <summary>
        /// 删除事项
        /// </summary>
        static void DeleteTodo(TodoManager manager)
        {
            Console.Write("请输入要删除的事项编号: ");
            if (int.TryParse(Console.ReadLine(), out int id))
            {
                manager.DeleteTodo(id);
            }
            else
            {
                Console.WriteLine("✗ 请输入有效的编号!");
            }
        }
    }
}

代码讲解:

  • 使用 switch 语句根据用户选择执行不同操作
  • Console.Clear():清屏使界面更整洁
  • Console.ReadKey():等待用户按键,避免信息一闪而过
  • 将每个操作封装成独立方法,使主程序更清晰

🎮 运行演示

===== 待办事项管理系统 =====
欢迎使用!

✓ 已加载 0 条待办事项

===== 待办事项管理 =====
1. 添加事项
2. 查看所有事项
3. 标记完成
4. 删除事项
5. 统计信息
6. 保存并退出
========================
请选择操作: 1

请输入待办事项: 学习 C# 面向对象编程
✓ 添加成功!

按任意键继续...

===== 待办事项管理 =====
1. 添加事项
2. 查看所有事项
3. 标记完成
4. 删除事项
5. 统计信息
6. 保存并退出
========================
请选择操作: 1

请输入待办事项: 完成项目实战
✓ 添加成功!

按任意键继续...

===== 待办事项管理 =====
1. 添加事项
2. 查看所有事项
3. 标记完成
4. 删除事项
5. 统计信息
6. 保存并退出
========================
请选择操作: 2

===== 待办事项列表 =====

未完成:
[ ] 1. 学习 C# 面向对象编程
[ ] 2. 完成项目实战
===========================

按任意键继续...

===== 待办事项管理 =====
1. 添加事项
2. 查看所有事项
3. 标记完成
4. 删除事项
5. 统计信息
6. 保存并退出
========================
请选择操作: 3

请输入要标记的事项编号: 1
✓ 已标记为完成!

按任意键继续...

===== 待办事项管理 =====
1. 添加事项
2. 查看所有事项
3. 标记完成
4. 删除事项
5. 统计信息
6. 保存并退出
========================
请选择操作: 5

===== 统计信息 =====
总数: 2
已完成: 1
未完成: 1
完成率: 50.0%
====================

按任意键继续...

===== 待办事项管理 =====
1. 添加事项
2. 查看所有事项
3. 标记完成
4. 删除事项
5. 统计信息
6. 保存并退出
========================
请选择操作: 6

✓ 数据已保存!

感谢使用!再见!

📚 知识点总结

这个项目用到了以下知识点:

知识点说明在项目中的应用
面向对象类、属性、方法TodoItem 和 TodoManager 类
集合List<T>存储所有待办事项
LINQ查询和筛选FirstOrDefault、Where、Count
文件 I/OStreamWriter/StreamReader数据的保存和加载
字符串操作Split、IsNullOrWhiteSpace解析文件数据
异常处理try-catch处理文件读写异常
日期时间DateTime记录创建时间
方法重载override ToString()自定义对象显示方式

💡 代码优化建议

1. 使用 JSON 格式存储

使用 System.Text.Json 或 Newtonsoft.Json 可以更方便地序列化对象:

using System.Text.Json;

// 保存
string json = JsonSerializer.Serialize(todoItems);
File.WriteAllText(filePath, json);

// 加载
string json = File.ReadAllText(filePath);
todoItems = JsonSerializer.Deserialize<List<TodoItem>>(json);

2. 添加优先级功能

public enum Priority
{
    Low,
    Medium,
    High
}

public class TodoItem
{
    public Priority Priority { get; set; }
    // ...
}

3. 添加截止日期

public class TodoItem
{
    public DateTime? DueDate { get; set; }
    
    public bool IsOverdue()
    {
        return DueDate.HasValue && DueDate.Value < DateTime.Now && !IsCompleted;
    }
}

4. 实现自动保存

每次修改数据后自动保存:

public void AddTodo(string content)
{
    // ... 添加逻辑
    AutoSave();
}

private void AutoSave()
{
    try
    {
        SaveToFile();
    }
    catch
    {
        // 静默失败,不打断用户操作
    }
}

🚀 扩展功能建议

完成基本功能后,可以尝试添加:

  1. 搜索功能

    • 按关键词搜索待办事项
    • 按状态筛选(已完成/未完成)
    • 按日期范围查询
  2. 分类管理

    • 为待办事项添加分类标签
    • 按分类查看和管理
  3. 提醒功能

    • 设置提醒时间
    • 显示即将到期的事项
  4. 数据导出

    • 导出为 CSV 格式
    • 导出为 Markdown 清单
  5. 撤销功能

    • 实现操作历史记录
    • 支持撤销上一步操作
  6. 批量操作

    • 批量标记完成
    • 批量删除已完成事项

🎯 练习任务

  1. 基础任务:完整实现上述代码,确保所有功能正常运行

  2. 进阶任务:添加编辑功能,允许修改待办事项的内容

  3. 挑战任务:实现优先级功能,支持高、中、低三个等级

  4. 超级挑战:实现分类功能,支持为每个待办事项设置分类标签

参考实现:添加编辑功能

// 在 TodoManager 类中添加
public void EditTodo(int id, string newContent)
{
    var todo = todoItems.FirstOrDefault(t => t.Id == id);
    
    if (todo == null)
    {
        Console.WriteLine("✗ 找不到该事项!");
        return;
    }
    
    if (string.IsNullOrWhiteSpace(newContent))
    {
        Console.WriteLine("✗ 内容不能为空!");
        return;
    }
    
    todo.Content = newContent;
    Console.WriteLine("✓ 修改成功!");
}

// 在主程序的菜单中添加选项
case "7":
    EditTodo(manager);
    break;

static void EditTodo(TodoManager manager)
{
    Console.Write("请输入要编辑的事项编号: ");
    if (int.TryParse(Console.ReadLine(), out int id))
    {
        Console.Write("请输入新的内容: ");
        string newContent = Console.ReadLine();
        manager.EditTodo(id, newContent);
    }
    else
    {
        Console.WriteLine("✗ 请输入有效的编号!");
    }
}

📝 项目小结

恭喜你完成了第二个项目!通过这个项目,你应该:

  • ✅ 掌握了面向对象的基本应用
  • ✅ 学会了使用 List<T> 管理数据
  • ✅ 理解了文件读写的基本操作
  • ✅ 熟练使用 LINQ 进行数据查询
  • ✅ 学会了如何设计类和方法
  • ✅ 实现了数据的持久化存储

🎯 下一步

完成待办事项管理项目后,下一个项目我们要做一个"学生信息管理系统",学习更复杂的 CRUD 操作和数据统计功能!

下一个项目:学生管理系统 →

💪 自我检测

  • [ ] 能够独立定义类和属性
  • [ ] 会使用 List<T> 存储和管理数据
  • [ ] 理解如何使用 LINQ 查询数据
  • [ ] 掌握文件的读写操作
  • [ ] 能够实现数据的持久化
  • [ ] 知道如何处理用户输入和异常

第二个项目完成了!你已经掌握了面向对象和数据管理的基础!继续加油!💪

最近更新: 2025/12/27 14:02
Contributors: 王长安
Prev
项目1 - 控制台计算器
Next
项目3 - 学生信息管理系统