泛型类型概述 Generic types overview

本文内容

在 .NET 中,开发人员随时会使用泛型,有时隐式使用,有时显式使用。在 .NET 中使用 LINQ 时,你是否曾经注意到,使用的正是 IEnumerable<T>或者,你是否曾经看到过有关使用实体框架来与数据库通信的“泛型存储库”在线示例,其中的大多数方法返回 IQueryable<T>?你可能很想知道,这些示例中的 T 是什么意思,为什么要使用它?

泛型在 .NET Framework 2.0 中首次引入,它本质上是一个“代码模板”,可让开发人员定义类型安全)数据结构,无需处理实际数据类型。例如,List<T> 是一个可以声明的泛型集合,可与 List<int>List<string>List<Person> 等任何类型结合使用。

为方便理解泛型的作用,让我们看看添加泛型之前和之后的一个特定类:ArrayList在 .NET Framework 1.0 中,ArrayList 元素属于 Object 类型。这意味着添加的任何元素都会以静默方式转换为 Object从列表读取元素时,会发生相同的情况。此过程称为装箱和取消装箱,它会影响性能。但更重要的是,在编译时无法确定列表中的数据类型。这就使得某些代码不太可靠。泛型解决了此问题,它可以定义每个列表实例将要包含的数据类型。例如,只能将整数添加到 List<int>,只能将人员添加到 List<Person>

泛型还可以在运行时使用。这意味着,运行时知道你要使用的数据结构类型,并可以更高效地将数据结构存储在内存中。

下面的示例是一个小程序,演示了在运行时如何有效地了解数据结构类型:

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. namespace GenericsExample {
  6. class Program {
  7. static void Main(string[] args) {
  8. //generic list
  9. List<int> ListGeneric = new List<int> { 5, 9, 1, 4 };
  10. //non-generic list
  11. ArrayList ListNonGeneric = new ArrayList { 5, 9, 1, 4 };
  12. // timer for generic list sort
  13. Stopwatch s = Stopwatch.StartNew();
  14. ListGeneric.Sort();
  15. s.Stop();
  16. Console.WriteLine($"Generic Sort: {ListGeneric} \n Time taken: {s.Elapsed.TotalMilliseconds}ms");
  17. //timer for non-generic list sort
  18. Stopwatch s2 = Stopwatch.StartNew();
  19. ListNonGeneric.Sort();
  20. s2.Stop();
  21. Console.WriteLine($"Non-Generic Sort: {ListNonGeneric} \n Time taken: {s2.Elapsed.TotalMilliseconds}ms");
  22. Console.ReadLine();
  23. }
  24. }
  25. }

此程序将生成类似下面的输出:

  1. Generic Sort: System.Collections.Generic.List`1[System.Int32]
  2. Time taken: 0.0034ms
  3. Non-Generic Sort: System.Collections.ArrayList
  4. Time taken: 0.2592ms

在此处可以看到的第一个优点是,泛型列表的排序比非泛型列表要快得多。还可以看到,泛型列表的类型是不同的 ([System.Int32]),而非泛型列表的类型已通用化。由于运行时知道泛型 List<int> 的类型是 Int32,因此可以将列表元素存储在内存中的基础整数数组内;而非泛型 ArrayList 必须将每个列表元素强制转换为对象。如本示例中所示,多余的强制转换会占用时间,降低列表排序的速度。

运行时知道泛型类型的另一个优点是可以改善调试体验。在 C# 中调试泛型时,可以知道数据结构中每个元素的类型。如果不使用泛型,则无从知道每个元素的类型是什么。

请参阅See also