泛型向 .NET 引入了类型参数的概念。 泛型使得可以设计类和方法,将一个或多个类型参数的定义推迟到在代码中使用该类或方法时。 例如,通过使用泛型类型参数 T
,可以编写一个供其他客户端代码使用的单个类,从而避免了运行时强制转换或装箱操作的成本或风险,如下所示:
// Declare the generic class.
public class GenericList<T>
{
public void Add(T item) { }
}
public class ExampleClass { }
class TestGenericList
{
static void Main()
{
// Create a list of type int.
GenericList<int> list1 = new();
list1.Add(1);
// Create a list of type string.
GenericList<string> list2 = new();
list2.Add("");
// Create a list of type ExampleClass.
GenericList<ExampleClass> list3 = new();
list3.Add(new ExampleClass());
}
}
泛型类和方法在可重用性、类型安全性和效率方面具有非泛型类和方法无法达到的优势。 泛型类型参数在编译过程中替换为类型参数。 在前面的示例中,编译器将 T
替换为 int
。 泛型最常用于集合及操作这些集合的方法。 命名空间 System.Collections.Generic 包含多个基于泛型的集合类。 不推荐使用非泛型集合,例如 ArrayList ,这些集合仅用于兼容性目的。 有关详细信息,请参阅 .NET中的
还可以创建自定义泛型类型和方法,以提供自己的通用解决方案和设计模式,这些模式是类型安全且高效的。 下面的代码示例演示了一个简单的泛型链接列表类,用于演示目的。 (在大多数情况下,应使用 List<T> .NET 提供的类,而不是创建自己的类。类型参数 T
用于多个位置,其中具体类型通常用于指示列表中存储的项的类型:
- 在
AddHead
方法中作为方法参数的类型。 - 在
Data
嵌套类中作为Node
属性的返回类型。 - 在嵌套类中作为私有成员
data
的类型。
T
可用于嵌套 Node
类。 当GenericList<T>
被实例化为一个具体类型时,例如为GenericList<int>
,每个T
实例都替换为int
。
// Type parameter T in angle brackets.
public class GenericList<T>
{
// The nested class is also generic, and
// holds a data item of type T.
private class Node(T t)
{
// T as property type.
public T Data { get; set; } = t;
public Node? Next { get; set; }
}
// First item in the linked list
private Node? head;
// T as parameter type.
public void AddHead(T t)
{
Node n = new(t);
n.Next = head;
head = n;
}
// T in method return type.
public IEnumerator<T> GetEnumerator()
{
Node? current = head;
while (current is not null)
{
yield return current.Data;
current = current.Next;
}
}
}
下面的代码示例演示客户端代码如何使用泛型 GenericList<T>
类创建整数列表。 如果更改类型参数,以下代码将创建字符串列表或任何其他自定义类型:
// A generic list of int.
GenericList<int> list = new();
// Add ten int values.
for (int x = 0; x < 10; x++)
{
list.AddHead(x);
}
// Write them to the console.
foreach (int i in list)
{
Console.WriteLine(i);
}
Console.WriteLine("Done");
注释
泛型类型不限于类。 前面的示例使用 class
类型,但可以定义泛型 interface
和 struct
类型,包括 record
类型。
泛型概述
- 使用泛型类型最大限度地提高代码重用、类型安全性和性能。
- 泛型的最常见用途是创建集合类。
- .NET 类库包含命名空间中的 System.Collections.Generic 多个泛型集合类。 应尽可能使用泛型集合,而不是命名空间 ArrayList 中的 System.Collections 类。
- 可以创建自己的泛型接口、类、方法、事件和委托。
- 可以限制泛型类,以启用对特定数据类型的方法的访问。
- 可以使用反射在运行时获取有关泛型数据类型中使用的类型的信息。
C# 语言规范
有关详细信息,请参阅 C# 语言规范。