C# 中的泛型:为什么需要以及如何在实践中使用

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C# 中的泛型:为什么需要以及如何在实践中使用



泛型(Generics)是 C# 语言的关键特性之一,它允许编写灵活、可复用且类型安全的代码。在本文中,我们将探讨为什么需要泛型,它们如何在底层工作,并展示在实际项目中应用它们的实用示例。



什么是泛型以及为什么需要它们?



想象一下,你需要实现一个交换两个值的方法。如果没有泛型,你必须为每种数据类型编写单独的版本:



// 没有泛型——代码重复void SwapInt(ref int a, ref int b) { int temp = a; a = b; b = temp; }void SwapString(ref string a, ref string b) { string temp = a; a = b; b = temp; }// ... 每个类型都要这样写


使用泛型,这个问题可以优雅地解决:



// 使用泛型——一个方法适用于所有类型void Swap<T>(ref T a, ref T b){    T temp = a;    a = b;    b = temp;}

// 使用方式int x = 1, y = 2;Swap(ref x, ref y); // T = int

string s1 = "Hello", s2 = "World";Swap(ref s1, ref s2); // T = string


泛型的主要优势:

  • 类型安全——类型错误在编译阶段即可捕获
  • 性能——避免值类型的装箱/拆箱
  • 代码复用——一个类/方法可处理任何类型
  • 可读性——代码更清晰、更简洁


泛型类与结构体



泛型最常见的应用示例是集合。无需为每种类型编写自己的类,我们可以创建泛型类:



public class MyList<T>{    private T[] _items;    private int _count;

public MyList(int capacity = 4) { _items = new T[capacity]; _count = 0; }

public void Add(T item) { if (_count == _items.Length) { Array.Resize(ref _items, _items.Length * 2); } _items[_count++] = item; }

public T Get(int index) { if (index < 0 || index >= _count) throw new IndexOutOfRangeException(); return _items[index]; }

public int Count => _count;}

// 使用方式var numbers = new MyList<int>();numbers.Add(10);numbers.Add(20);

var names = new MyList<string>();names.Add("Alice");


请注意:创建实例时,我们在尖括号 <T> 中指定具体类型。编译器会将此类型替换到所有使用 T 的位置。



泛型方法与约束(constraints)



有时需要对类型 T 施加限制。例如,确保类型实现了特定接口或具有无参构造函数:



// 约束:T 必须实现 IComparable<T>public T GetMax<T>(T a, T b) where T : IComparable<T>{    return a.CompareTo(b) > 0 ? a : b;}

// 约束:T 必须具有无参构造函数public class Factory<T> where T : new(){ public T Create() { return new T(); }}

// 约束:T 必须是值类型(struct)public struct Nullable<T> where T : struct{ private T _value; private bool _hasValue;

public Nullable(T value) { _value = value; _hasValue = true; }

public T Value => _hasValue ? _value : throw new InvalidOperationException(); public bool HasValue => _hasValue;}


主要的约束类型: