C# 中泛型(Generics)简介
泛型(Generics)是 C# 语言中最强大的功能之一,自 .NET Framework 2.0 引入。它们允许创建能够处理任何数据类型、同时保持严格类型检查的类、方法和接口。在本文中,我们将探讨C# 中为什么需要泛型,如何使用它们以及它们为开发者带来的优势。
假设您需要编写一个交换两个变量值的方法。没有泛型时,您必须为每种类型创建单独的方法:SwapInt、SwapString、SwapDouble 等等。而使用泛型,这个任务可以通过一个通用函数解决。
泛型的主要优势
1. 编译时类型安全
泛型在编译时而非运行时提供类型检查。这意味着与类型不匹配相关的错误将在开发早期被发现。
// 没有泛型 - 运行时可能出错ArrayList list = new ArrayList();list.Add(123);list.Add("строка");int number = (int)list[1]; // InvalidCastException!
// 使用泛型 - 编译时出错List<int> numbers = new List<int>();numbers.Add(123);numbers.Add("строка"); // 编译错误!2. 性能
使用泛型可以避免值类型的装箱(boxing)和拆箱(unboxing)操作。这显著提高了处理集合时的性能。
// 装箱/拆箱 - 速度慢ArrayList list = new ArrayList();list.Add(42); // boxingint value = (int)list[0]; // unboxing
// 泛型 - 速度快,无需 boxingList<int> list = new List<int>();list.Add(42); // 无需 boxingint value = list[0]; // 无需 unboxing3. 代码重用
一个泛型类或方法可以处理任何数据类型,从而避免了代码重复。
创建和使用泛型
泛型类
让我们看一个创建用于存储键值对的泛型类的示例:
public class Pair<TFirst, TSecond>{ public TFirst First { get; set; } public TSecond Second { get; set; } public Pair(TFirst first, TSecond second) { First = first; Second = second; } public void Display() { Console.WriteLine($"First: {First}, Second: {Second}"); }}
// 使用var pair1 = new Pair<int, string>(1, "один");var pair2 = new Pair<string, double>("PI", 3.14159);
pair1.Display(); // First: 1, Second: одинpair2.Display(); // First: PI, Second: 3.14159泛型方法
方法也可以是泛型的。这是一个经典示例——值交换方法:
public static void Swap<T>(ref T a, ref T b){ T temp = a; a = b; b = temp;}
// 使用int x = 5, y = 10;Swap<int>(ref x, ref y);Console.WriteLine($"x = {x}, y = {y}"); // x = 10, y = 5
string s1 = "Hello", s2 = "World";Swap(ref s1, ref s2); // 类型可以省略Console.WriteLine($"s1 = {s1}, s2 = {s2}"); // s1 = World, s2 = Hello泛型接口
带有泛型的接口允许创建灵活的契约:
public interface IRepository<T>{ T GetById(int id); void Add(T entity); void Update(T entity); void Delete(int id);}
public class UserRepository : IRepository<User>{ public User GetById(int id) { // 获取用户的实现 return new User(); } public void Add(User user) { // 添加的实现 } public void Update(User user) { // 更新的实现 }