C# Academy · 课时

泛型类

可复用的容器类型。

第 2 / 4 课13 个步骤

泛型类 是 CoddyKit 上的免费 C# Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 4 节课。

什么是泛型类?

泛型类会在类名后的尖括号中声明一个或多个类型参数。这些参数可以在整个类中用于字段、属性、方法签名和返回类型。

这样,您只需编写一个容器或服务,就能支持多种元素类型,同时保持强类型。

class Box<T>
{
    public T Value { get; set; }
}

构造泛型类

创建实例时,需要提供具体的类型参数。Box<int> 和 Box<string> 是不同的构造类型。

每种构造类型的行为都相当于将其中的 T 在各处替换为实际类型。

using System;

class Box<T> { public T Value { get; set; } }

class Program
{
    static void Main()
    {
        var b = new Box<int> { Value = 7 };
        Console.WriteLine(b.Value);
    }
}

泛型字段和属性

类型参数可以作为字段和属性的类型。栈、队列或缓存通常会将数据存储在由 T 构成的数组或列表中。

内部存储无需类型转换即可保持类型安全。

class Pair<T>
{
    public T First;
    public T Second;
}

多个类型参数

类可以接受多个类型参数。键值对或字典风格的类型通常会使用两个类型参数。

存在多个类型参数时,使用 TKey 和 TValue 之类的描述性名称可以提高可读性。

class Entry<TKey, TValue>
{
    public TKey Key { get; set; }
    public TValue Value { get; set; }
}

简单的泛型栈

下面是一个基于 List<T> 构建的小型泛型栈。Push 添加到末尾,Pop 从末尾移除。

同一个类可以处理整数、字符串,以及任何引用类型或值类型。

using System;
using System.Collections.Generic;

class MyStack<T>
{
    private readonly List<T> items = new();
    public void Push(T item) => items.Add(item);
    public T Pop()
    {
        var i = items[^1];
        items.RemoveAt(items.Count - 1);
        return i;
    }
}

class Program
{
    static void Main()
    {
        var s = new MyStack<string>();
        s.Push("a");
        s.Push("b");
        Console.WriteLine(s.Pop());
    }
}

泛型类中的泛型方法

泛型类还可以在单个方法上声明额外的类型参数。这些方法级别的参数与类级别的参数彼此独立。

这增加了灵活性,例如可以将存储的类型转换为另一种类型。

class Box<T>
{
    public T Value;
    public TOut Map<TOut>(Func<T, TOut> f) => f(Value);
}

类的约束

与方法一样,泛型类也可以使用 where 约束其类型参数。使用该参数的每个成员都会受到此约束的影响。

下面的 where T : class 允许为 T 赋值 null,并进行引用比较。

class Repository<T> where T : class
{
    private T current;
    public bool IsEmpty => current is null;
}

静态成员按类型独立存在

每种构造泛型类型都会拥有自己的静态字段副本。Counter<int> 和 Counter<string> 分别记录独立的计数。

这是泛型类与非泛型类之间一个细微但重要的区别。

class Counter<T>
{
    public static int Count;
}

泛型类中的默认值

在泛型类中,您经常需要为类型为 T 的字段设置初始值。当类型可以从上下文确定时,请使用 default(T) 或更简短的 default。

对于引用类型,它会产生 null;对于值类型,它会产生零值。

class Slot<T>
{
    public T Value = default!;
    public bool HasValue { get; private set; }
}

继承泛型类

您可以从泛型基类派生。子类可以固定类型参数,也可以自身保持为泛型类。

固定类型参数会使基类专门化;保持泛型则会将参数继续向上传递。

class Box<T> { public T Value; }

class IntBox : Box<int> { }

class NamedBox<T> : Box<T> { public string Name; }

泛型与内置集合

.NET 基础类库中充满了泛型类,例如 List<T>、Dictionary<TKey, TValue> 和 Queue<T>。它们体现了泛型类设计在日常开发中的价值。

编写自己的泛型类型,可以延续这种安全且可复用的风格。

using System.Collections.Generic;

var scores = new Dictionary<string, int>();
scores["ada"] = 95;

快速检查

测试您对泛型类的理解。

总结

泛型类会在类名后声明类型参数,并将它们用于字段、属性和方法。使用具体类型参数构造泛型类时,会创建不同的类型。

泛型类可以添加方法级别的类型参数、包含 where 约束、被继承,并保存按类型独立的静态状态。内置集合就是最典型的示例。

免费开始

用 AI 导师学习 C# — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
93
课程
346

常见问题解答

「泛型类」课时是免费的吗?

是的 — 「泛型类」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 4 节课。

「泛型类」这节课中我会学到什么?

可复用的容器类型。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C# Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「泛型类」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C# Academy 课中编写并运行代码吗?

能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 泛型方法
  2. 泛型类
  3. where 约束
  4. 泛型接口
← 返回 C# Academy