Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
  • 5.2 泛型与泛型集合

5.2 泛型与泛型集合

概述

泛型(Generics)是C# 2.0引入的核心特性,它允许开发者编写可重用的、类型安全的代码,而无需为每种数据类型重复编写相同的逻辑。泛型集合则是基于泛型实现的强类型集合类(如List<T>、Dictionary<TKey, TValue>等),相比非泛型集合(如ArrayList),它们在性能和类型安全性上有显著优势。


泛型基础

1. 泛型类型定义

通过<T>语法声明泛型类型参数,T代表占位符类型(可替换为任意具体类型):

public class GenericBox<T>
{
    public T Content { get; set; }
}

// 使用示例
var intBox = new GenericBox<int> { Content = 42 };
var stringBox = new GenericBox<string> { Content = "Hello" };

2. 泛型方法

方法也可以定义为泛型,独立于其所属类:

public T Max<T>(T a, T b) where T : IComparable<T>
{
    return a.CompareTo(b) > 0 ? a : b;
}

// 调用示例
int result = Max(10, 20); // 自动推断类型为int

3. 类型约束

通过where关键字限制泛型参数的类型范围:

  • where T : struct:必须是值类型
  • where T : class:必须是引用类型
  • where T : new():必须有无参构造函数
  • where T : BaseClass:必须继承自指定基类
  • where T : Interface:必须实现指定接口

泛型集合

1. 常用泛型集合类

集合类描述示例
List<T>动态数组var list = new List<int>();
Dictionary<TKey,TValue>键值对集合var dict = new Dictionary<string, int>();
HashSet<T>不重复元素的集合var set = new HashSet<string>();
Queue<T>先进先出队列var queue = new Queue<double>();
Stack<T>后进先出栈var stack = new Stack<bool>();

2. 与非泛型集合对比

// 非泛型ArrayList(不推荐)
ArrayList oldList = new ArrayList();
oldList.Add(1);      // 装箱(性能损耗)
oldList.Add("text"); // 允许任意类型(类型不安全)
int num = (int)oldList[0]; // 需要显式拆箱

// 泛型List<T>(推荐)
List<int> newList = new List<int>();
newList.Add(1);      // 无装箱
// newList.Add("text"); // 编译时报错
int num = newList[0]; // 直接访问

高级泛型特性

1. 协变与逆变(C# 4.0+)

  • 协变(out T):允许使用派生程度更大的类型(如IEnumerable<Cat>赋值给IEnumerable<Animal>)
  • 逆变(in T):允许使用派生程度更小的类型(如Action<Animal>赋值给Action<Cat>)
// 协变示例
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings; // 合法,因为IEnumerable<out T>

// 逆变示例
Action<object> actObject = obj => Console.WriteLine(obj);
Action<string> actString = actObject; // 合法,因为Action<in T>

2. 默认值表达式

使用default关键字获取泛型类型的默认值:

T GetDefault<T>() => default(T);

Console.WriteLine(GetDefault<int>());    // 输出: 0
Console.WriteLine(GetDefault<string>()); // 输出: null

最佳实践

  1. 优先使用泛型集合:避免非泛型集合带来的装箱/拆箱开销和类型安全问题
  2. 合理使用约束:通过约束提高代码可读性并减少运行时错误
  3. 避免过度泛化:只在需要处理多种数据类型时使用泛型,否则会增加代码复杂度

示例项目:泛型缓存器

public class GenericCache<TKey, TValue>
{
    private readonly Dictionary<TKey, TValue> _cache = new Dictionary<TKey, TValue>();
    
    public void Add(TKey key, TValue value)
    {
        if (!_cache.ContainsKey(key))
        {
            _cache.Add(key, value);
        }
    }
    
    public TValue Get(TKey key) => _cache.TryGetValue(key, out var value) ? value : default;
}

// 使用示例
var cache = new GenericCache<int, string>();
cache.Add(1, "Apple");
string result = cache.Get(1); // 返回"Apple"
Last Updated:: 5/3/25, 11:01 PM