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

    • 📚 进阶内容
    • 第1章 - 集合
    • 第2章 - 泛型
    • 第3章 - LINQ
    • 第4章 - 委托与事件
    • 第5章 - 异常处理
    • 第6章 - 文件操作
    • 第7章 - 异步编程
    • 第8章 - 反射
    • 第9章 - 特性
    • 第10章 - 扩展方法

第1章 - 集合

嗨,朋友!我是长安。

在基础教程中,我们学习了数组,但数组有个缺点:大小固定,不能动态增减。这一章我们要学习"集合",它们比数组更灵活、更强大!

🤔 什么是集合?

集合就像一个可以自动伸缩的容器,可以随时添加、删除元素。

类比:

  • 数组:像一排固定的储物柜,有10个柜子就是10个,不能增减
  • 集合:像一个可伸缩的背包,想装多少就装多少

🌟 常用集合类型

C# 提供了多种集合类型,每种都有特定的用途:

集合类型特点适用场景
List<T>动态数组最常用,类似数组但可变长
Dictionary<TKey, TValue>键值对需要通过键快速查找值
HashSet<T>不重复集合需要存储唯一值
Queue<T>队列先进先出(FIFO)
Stack<T>栈后进先出(LIFO)

📚 List<T> - 动态数组

List<T> 是最常用的集合,T 表示泛型(下一章会详细讲)。

创建 List

using System;
using System.Collections.Generic; // 必须引入这个命名空间

namespace CollectionsDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建一个存储整数的 List
            List<int> numbers = new List<int>();
            
            // 创建时初始化
            List<string> names = new List<string> { "张三", "李四", "王五" };
            
            // 输出
            Console.WriteLine($"names 有 {names.Count} 个元素");
        }
    }
}

添加元素

List<string> fruits = new List<string>();

// 添加单个元素
fruits.Add("苹果");
fruits.Add("香蕉");
fruits.Add("橙子");

// 添加多个元素
fruits.AddRange(new[] { "葡萄", "西瓜" });

// 在指定位置插入
fruits.Insert(1, "草莓"); // 在索引1的位置插入

Console.WriteLine($"水果数量:{fruits.Count}");

访问元素

List<string> fruits = new List<string> { "苹果", "香蕉", "橙子" };

// 通过索引访问
Console.WriteLine(fruits[0]);  // 输出:苹果
Console.WriteLine(fruits[1]);  // 输出:香蕉

// 使用 foreach 遍历
foreach (string fruit in fruits)
{
    Console.WriteLine(fruit);
}

// 使用 for 循环遍历
for (int i = 0; i < fruits.Count; i++)
{
    Console.WriteLine($"{i}: {fruits[i]}");
}

删除元素

List<string> fruits = new List<string> { "苹果", "香蕉", "橙子", "香蕉" };

// 删除指定元素(只删除第一个匹配的)
fruits.Remove("香蕉");

// 删除指定索引的元素
fruits.RemoveAt(0);

// 删除所有匹配的元素
fruits.RemoveAll(f => f == "香蕉");

// 清空所有元素
fruits.Clear();

查找元素

List<string> fruits = new List<string> { "苹果", "香蕉", "橙子" };

// 检查是否包含某个元素
bool hasApple = fruits.Contains("苹果"); // true

// 查找元素的索引
int index = fruits.IndexOf("香蕉"); // 1

// 查找满足条件的第一个元素
string fruit = fruits.Find(f => f.StartsWith("橙")); // "橙子"

// 查找满足条件的所有元素
List<string> result = fruits.FindAll(f => f.Length > 2);

完整示例:学生成绩管理

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

namespace ListDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建成绩列表
            List<int> scores = new List<int>();
            
            // 输入5个学生的成绩
            Console.WriteLine("请输入5个学生的成绩:");
            for (int i = 0; i < 5; i++)
            {
                Console.Write($"学生{i + 1}的成绩:");
                int score = int.Parse(Console.ReadLine());
                scores.Add(score);
            }
            
            // 计算平均分
            double average = scores.Average();
            Console.WriteLine($"\n平均分:{average:F2}");
            
            // 找出最高分和最低分
            int maxScore = scores.Max();
            int minScore = scores.Min();
            Console.WriteLine($"最高分:{maxScore}");
            Console.WriteLine($"最低分:{minScore}");
            
            // 统计及格人数(≥60分)
            int passCount = scores.Count(s => s >= 60);
            Console.WriteLine($"及格人数:{passCount}");
            
            // 按分数排序(从高到低)
            scores.Sort((a, b) => b.CompareTo(a));
            Console.WriteLine("\n成绩排名(从高到低):");
            for (int i = 0; i < scores.Count; i++)
            {
                Console.WriteLine($"第{i + 1}名:{scores[i]}分");
            }
            
            Console.ReadKey();
        }
    }
}

📖 Dictionary<TKey, TValue> - 字典

字典存储键值对,可以通过键快速查找值。

创建 Dictionary

// 创建一个存储学生姓名和成绩的字典
Dictionary<string, int> studentScores = new Dictionary<string, int>();

// 创建时初始化
Dictionary<string, string> phoneBook = new Dictionary<string, string>
{
    { "张三", "138-1234-5678" },
    { "李四", "139-8765-4321" },
    { "王五", "150-1111-2222" }
};

添加和修改元素

Dictionary<string, int> scores = new Dictionary<string, int>();

// 添加元素
scores.Add("张三", 85);
scores.Add("李四", 92);

// 使用索引添加/修改
scores["王五"] = 78; // 如果不存在就添加,存在就修改
scores["张三"] = 88; // 修改张三的成绩

// 尝试添加(如果键已存在则返回 false)
bool added = scores.TryAdd("李四", 95); // false,因为李四已存在

访问元素

Dictionary<string, int> scores = new Dictionary<string, int>
{
    { "张三", 85 },
    { "李四", 92 },
    { "王五", 78 }
};

// 通过键访问值
int score = scores["张三"]; // 85

// 安全访问(如果键不存在不会报错)
if (scores.TryGetValue("张三", out int zhangScore))
{
    Console.WriteLine($"张三的成绩:{zhangScore}");
}

// 遍历字典
foreach (KeyValuePair<string, int> item in scores)
{
    Console.WriteLine($"{item.Key}: {item.Value}分");
}

// 或者这样遍历
foreach (var item in scores)
{
    Console.WriteLine($"{item.Key}: {item.Value}分");
}

删除和查找

Dictionary<string, int> scores = new Dictionary<string, int>
{
    { "张三", 85 },
    { "李四", 92 }
};

// 删除元素
scores.Remove("张三");

// 检查是否包含某个键
bool hasKey = scores.ContainsKey("李四"); // true

// 检查是否包含某个值
bool hasValue = scores.ContainsValue(92); // true

// 获取所有的键
var keys = scores.Keys;

// 获取所有的值
var values = scores.Values;

// 清空
scores.Clear();

完整示例:电话簿

using System;
using System.Collections.Generic;

namespace DictionaryDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<string, string> phoneBook = new Dictionary<string, string>
            {
                { "张三", "138-1234-5678" },
                { "李四", "139-8765-4321" }
            };
            
            while (true)
            {
                Console.WriteLine("\n===== 电话簿 =====");
                Console.WriteLine("1. 添加联系人");
                Console.WriteLine("2. 查询电话");
                Console.WriteLine("3. 删除联系人");
                Console.WriteLine("4. 显示所有联系人");
                Console.WriteLine("0. 退出");
                Console.Write("请选择操作:");
                
                string choice = Console.ReadLine();
                
                switch (choice)
                {
                    case "1":
                        Console.Write("姓名:");
                        string name = Console.ReadLine();
                        Console.Write("电话:");
                        string phone = Console.ReadLine();
                        
                        if (phoneBook.ContainsKey(name))
                        {
                            Console.WriteLine("该联系人已存在!");
                        }
                        else
                        {
                            phoneBook.Add(name, phone);
                            Console.WriteLine("添加成功!");
                        }
                        break;
                        
                    case "2":
                        Console.Write("请输入姓名:");
                        string searchName = Console.ReadLine();
                        
                        if (phoneBook.TryGetValue(searchName, out string foundPhone))
                        {
                            Console.WriteLine($"{searchName}的电话是:{foundPhone}");
                        }
                        else
                        {
                            Console.WriteLine("未找到该联系人!");
                        }
                        break;
                        
                    case "3":
                        Console.Write("请输入要删除的姓名:");
                        string deleteName = Console.ReadLine();
                        
                        if (phoneBook.Remove(deleteName))
                        {
                            Console.WriteLine("删除成功!");
                        }
                        else
                        {
                            Console.WriteLine("未找到该联系人!");
                        }
                        break;
                        
                    case "4":
                        Console.WriteLine("\n所有联系人:");
                        foreach (var contact in phoneBook)
                        {
                            Console.WriteLine($"{contact.Key}: {contact.Value}");
                        }
                        break;
                        
                    case "0":
                        Console.WriteLine("再见!");
                        return;
                        
                    default:
                        Console.WriteLine("无效的选择!");
                        break;
                }
            }
        }
    }
}

🎯 HashSet<T> - 不重复集合

HashSet<T> 自动去除重复元素,适合需要存储唯一值的场景。

using System;
using System.Collections.Generic;

namespace HashSetDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            // 创建 HashSet
            HashSet<int> numbers = new HashSet<int>();
            
            // 添加元素(重复的会自动忽略)
            numbers.Add(1);
            numbers.Add(2);
            numbers.Add(2); // 这个2不会被添加
            numbers.Add(3);
            
            Console.WriteLine($"元素个数:{numbers.Count}"); // 输出:3
            
            // 遍历
            foreach (int num in numbers)
            {
                Console.WriteLine(num); // 输出:1 2 3
            }
            
            // 集合运算
            HashSet<int> set1 = new HashSet<int> { 1, 2, 3, 4 };
            HashSet<int> set2 = new HashSet<int> { 3, 4, 5, 6 };
            
            // 并集
            set1.UnionWith(set2);
            Console.WriteLine("并集:" + string.Join(", ", set1)); // 1, 2, 3, 4, 5, 6
            
            // 交集
            HashSet<int> set3 = new HashSet<int> { 1, 2, 3, 4 };
            set3.IntersectWith(set2);
            Console.WriteLine("交集:" + string.Join(", ", set3)); // 3, 4
            
            Console.ReadKey();
        }
    }
}

📝 本章小结

这一章我们学习了:

  • ✅ 集合的概念和优势
  • ✅ List<T> 动态数组的使用
  • ✅ Dictionary<TKey, TValue> 字典的使用
  • ✅ HashSet<T> 不重复集合的使用
  • ✅ 如何选择合适的集合类型

💡 集合选择建议

  • List<T>:默认选择,90% 的情况都用它
  • Dictionary<TKey, TValue>:需要通过键查找值时使用
  • HashSet<T>:需要存储唯一值时使用
  • Queue<T>:需要先进先出时使用
  • Stack<T>:需要后进先出时使用

🎯 下一步

掌握了集合的使用后,下一章我们要学习"泛型"——让你的代码更通用、更安全!

下一章:泛型 →

💪 练习题

  1. 创建一个 List,存储5个城市名称,然后按字母顺序排序并输出
  2. 创建一个 Dictionary,存储5个国家和对应的首都,实现查询功能
  3. 用 HashSet 存储一组数字,自动去除重复项
  4. 实现一个简单的购物车功能:可以添加商品、删除商品、显示所有商品
答案提示
  1. 使用 List<string>,然后调用 Sort() 方法
  2. 使用 Dictionary<string, string>,用 TryGetValue() 查询
  3. 直接添加到 HashSet<int> 中,重复的会自动去除
  4. 使用 Dictionary<string, int> 存储商品名和数量
最近更新: 2025/12/27 14:02
Contributors: 王长安
Prev
📚 进阶内容
Next
第2章 - 泛型