Collection Builders
Support collection expressions in custom types.
Collection Builders is a free C# Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C# Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Custom Types in Collection Expressions
Collection expressions are not limited to built-in types. With the [CollectionBuilder] attribute, your own type can be created from [...] syntax.
The CollectionBuilder Attribute
You apply [CollectionBuilder(typeof(Factory), "Create")] to your collection type. It names a static factory method the compiler calls to build instances.
Builder Method Signature
The builder method must be static and take a single ReadOnlySpan<T> parameter, returning your collection type. The compiler passes the elements as a span.
A Minimal Custom Collection
Here is a small immutable collection that opts into collection-expression creation via a builder.
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();Why ReadOnlySpan?
The span parameter lets the compiler hand over the elements with no intermediate allocation. Your builder copies them into whatever storage it needs.
It Must Be IEnumerable
The collection type has to implement IEnumerable<T> (matching the span element type) so the compiler knows the element type and can validate usage.
Generic Builders
Builders can be generic, supporting MyCollection<T>. The builder method takes ReadOnlySpan<T> and returns 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();Immutable Collections Benefit
Builders are how the .NET immutable collections (like ImmutableArray<T>) support collection expressions. The builder constructs the frozen instance from the span.
using System;
using System.Collections.Immutable;
ImmutableArray<int> nums = [1, 2, 3];
Console.WriteLine(nums.Length); // 3Spreads Work Too
Once a type has a builder, spreads work automatically inside its collection expressions, because the compiler still produces a single span of elements.
using System;
using System.Collections.Immutable;
ImmutableArray<int> a = [1, 2];
ImmutableArray<int> all = [..a, 3, 4];
Console.WriteLine(all.Length); // 4When to Add a Builder
Add a [CollectionBuilder] when you ship a custom collection and want callers to enjoy the concise [...] syntax, especially for immutable or specialized containers.
Putting It Together
A builder is just three pieces: the attribute, an IEnumerable<T> type, and a static Create(ReadOnlySpan<T>) method. With those, your type becomes a first-class collection-expression target.
Quick Check
Confirm the requirements for a collection builder.
Recap
You learned how custom types support collection expressions.
- Apply
[CollectionBuilder(typeof(Factory), "Create")]to the type. - The factory is a
staticmethod takingReadOnlySpan<T>. - The type must implement
IEnumerable<T>. - This is how
ImmutableArray<T>accepts[...].
Frequently asked questions
Is the “Collection Builders” lesson free?
Yes — the full text of “Collection Builders” is free to read here on the web, and the C# Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C# Academy course, upgrade to CoddyKit PRO.
What will I learn in “Collection Builders”?
Support collection expressions in custom types. You practise C# Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start C# Academy?
No prior experience is required. C# Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Collection Builders” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this C# Academy lesson?
Yes. Every C# Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Collection Expression Syntax
- The Spread Element
- Target Typing Collections
- Collection Builders