0Pricing
C# Academy · 课时

集合构建器

让自定义类型支持集合表达式。

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

集合表达式中的自定义类型

集合表达式并不局限于内置类型。借助 [CollectionBuilder] 特性,您自己的类型也可以通过 [...] 语法创建。

CollectionBuilder 特性

您可以将 [CollectionBuilder(typeof(Factory), "Create")] 应用于集合类型。它会指定一个静态工厂方法,编译器将调用该方法来构建实例。

构建器方法签名

构建器方法必须是 static,并接受单个 ReadOnlySpan<T> 参数,同时返回您的集合类型。编译器会将元素作为跨度传入。

最小自定义集合

这是一个小型不可变集合,它通过构建器支持集合表达式创建。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

[CollectionBuilder(typeof(IntBagBuilder), "Create")]
class IntBag : IEnumerable<int> {
    private readonly int[] items;
    public IntBag(ReadOnlySpan<int> data) => items = data.ToArray();
    public IEnumerator<int> GetEnumerator() => ((IEnumerable<int>)items).GetEnumerator();
    IEnumerator IEnumerable.GetEnumerator() => items.GetEnumerator();
}

static class IntBagBuilder {
    public static IntBag Create(ReadOnlySpan<int> data) => new IntBag(data);
}

IntBag bag = [1, 2, 3];
foreach (int n in bag) Console.Write(n + " "); // 1 2 3
Console.WriteLine();

为什么使用 ReadOnlySpan

跨度参数可以让编译器在没有中间分配的情况下传递元素。您的构建器会将这些元素复制到所需的存储中。

必须实现可枚举接口

集合类型必须实现 IEnumerable<T>(与跨度的元素类型匹配),这样编译器才能知道元素类型并验证用法。

泛型构建器

构建器可以是泛型的,从而支持 MyCollection<T>。构建器方法接受 ReadOnlySpan<T>,并返回 MyCollection<T>。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

[CollectionBuilder(typeof(BoxBuilder), "Create")]
class Box<T> : IEnumerable<T> {
    private readonly T[] items;
    public Box(ReadOnlySpan<T> d) => items = d.ToArray();
    public IEnumerator<T> GetEnumerator() => ((IEnumerable<T>)items).GetEnumerator();
    IEnumerator IEnumerable.GetEnumerator() => items.GetEnumerator();
}

static class BoxBuilder {
    public static Box<T> Create<T>(ReadOnlySpan<T> d) => new Box<T>(d);
}

Box<string> b = ["x", "y"];
foreach (var s in b) Console.Write(s + " "); // x y
Console.WriteLine();

不可变集合的优势

构建器是 .NET 不可变集合(例如 ImmutableArray<T>)支持集合表达式的方式。构建器会根据跨度构造冻结的实例。

using System;
using System.Collections.Immutable;

ImmutableArray<int> nums = [1, 2, 3];
Console.WriteLine(nums.Length); // 3

展开元素同样适用

类型拥有构建器后,其集合表达式中会自动支持展开元素,因为编译器仍然会生成一个包含所有元素的跨度。

using System;
using System.Collections.Immutable;

ImmutableArray<int> a = [1, 2];
ImmutableArray<int> all = [..a, 3, 4];
Console.WriteLine(all.Length); // 4

何时添加构建器

当您发布自定义集合并希望调用方享受简洁的 [...] 语法时,可以添加 [CollectionBuilder],尤其适用于不可变容器或专用容器。

综合运用

构建器只有三个组成部分:该特性、一个 IEnumerable<T> 类型,以及一个静态的 Create(ReadOnlySpan<T>) 方法。有了这些,您的类型就能作为一等集合表达式目标。

快速检查

确认集合构建器的要求。

回顾

您学习了自定义类型如何支持集合表达式。

  • 将 [CollectionBuilder(typeof(Factory), "Create")] 应用于该类型。
  • 工厂是一个接受 ReadOnlySpan<T> 的 static 方法。
  • 该类型必须实现 IEnumerable<T>。
  • ImmutableArray<T> 正是通过这种方式接受 [...] 的。

常见问题解答

「集合构建器」课时是免费的吗?

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

「集合构建器」这节课中我会学到什么?

让自定义类型支持集合表达式。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

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

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

「集合构建器」课时需要多长时间?

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

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

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

此课程中的所有课时

  1. 集合表达式语法
  2. 展开元素
  3. 集合的目标类型推断
  4. 集合构建器
← 返回 C# Academy