0Pricing
C# Academy · 课时

where 约束

约束类型参数。

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

约束存在的原因

默认情况下,类型参数 T 几乎会被当作 object 处理,因此编译器只允许对它执行很少的操作。使用 where 编写的约束会向编译器提供更多关于 T 的信息。

有了这些信息,您就可以安全地调用方法、创建实例或比较值。

void Show<T>(T value) where T : IFormattable
{
    // now ToString(format, provider) is available
}

接口约束

接口约束要求 T 实现指定的接口。这样,方法体就可以调用该接口的成员。

下面的 where T : IComparable<T> 保证存在 CompareTo 方法。

T Max<T>(T a, T b) where T : IComparable<T>
    => a.CompareTo(b) >= 0 ? a : b;

基类约束

您可以要求 T 派生自指定的基类。这样,泛型代码内部就可以使用该基类的成员。

在所有实体共享同一个基类型的框架中,这种做法很常见。

class Animal { public string Name = ""; }

string NameOf<T>(T a) where T : Animal => a.Name;

class 约束

where T : class 要求 T 为引用类型。这样就可以为其赋值 null,并检查引用相等性。

仓储、缓存以及任何存储可为空引用的组件通常都会使用它。

T? FindOrNull<T>(bool found, T value) where T : class
    => found ? value : null;

struct 约束

where T : struct 要求 T 为不可为空的值类型。这样,您可以将 T 作为值类型处理,并使用 T? 表示可为空的值类型。

只处理数字、枚举或小型结构的辅助工具会使用这种约束。

T? AsNullable<T>(T value) where T : struct
    => value;

new() 约束

new() 约束要求 T 具有公共无参数构造函数。这样,方法体就可以编写 new T()。

工厂和对象池依靠此约束以泛型方式创建实例。

using System;

class Program
{
    static T Make<T>() where T : new() => new T();

    static void Main()
    {
        var list = Make<System.Collections.Generic.List<int>>();
        Console.WriteLine(list.Count);
    }
}

组合约束

您可以为一个参数应用多个约束。排序规则要求先写 class 或 struct,然后是基类,接着是接口,最后写 new()。

这些约束写在单个 where 后面,并用逗号分隔。

T Build<T>() where T : class, IComparable<T>, new()
    => new T();

多个 where 子句

当方法或类包含多个类型参数时,每个参数都有自己的 where 子句。它们会依次书写。

这样可以清楚地区分每个参数对应的约束。

TResult Convert<TInput, TResult>(TInput x)
    where TInput : class
    where TResult : new()
    => new TResult();

可运行的约束示例

这个完整程序使用 IComparable<T> 约束查找两个值中较大的一个,同时适用于整数和字符串。

正是该约束使方法内部调用 CompareTo 成为合法操作。

using System;

class Program
{
    static T Max<T>(T a, T b) where T : IComparable<T>
        => a.CompareTo(b) >= 0 ? a : b;

    static void Main()
    {
        Console.WriteLine(Max(3, 9));
        Console.WriteLine(Max("apple", "pear"));
    }
}

notnull 和 unmanaged 约束

较新版本的 C# 增加了更多约束。where T : notnull 禁止可为空的类型,适合用作字典键。where T : unmanaged 将 T 限制为可直接映射的值类型,适用于底层代码。

这些约束可以在专门的场景中进一步提高安全性。

void Use<T>(T key) where T : notnull { }

unsafe void Raw<T>(T v) where T : unmanaged { }

约束带来能力,而非限制

约束看起来像是在限制类型,但实际上会解锁更多能力。没有约束时,您几乎无法操作 T;有了约束后,就可以使用它的成员。

请选择能让算法正常工作的最小约束,从而尽可能保持类型参数的灵活性。

// No constraint: only object members available
string Name<T>(T x) => x.ToString();

快速检查

测试您对 where 约束的理解。

总结

where 子句用于约束类型参数,包括接口、基类、class、struct、new()、notnull 和 unmanaged。每种约束都会为 T 解锁特定操作。

请按照正确顺序排列约束,为每个参数使用一个子句,并选择算法所需的最小约束。

常见问题解答

「where 约束」课时是免费的吗?

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

「where 约束」这节课中我会学到什么?

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

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

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

「where 约束」课时需要多长时间?

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

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

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

此课程中的所有课时

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