TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #3000 2.36K
День 2497. #ЗаметкиНаПолях
Используем Выражения Коллекций для Пользовательских Типов

В C#12 появились выражения коллекций — новый упрощённый синтаксис для инициализации коллекций:
int[] numbers = [1, 2, 3, 4, 5];
List<string> names = ["Alice", "Bob", "Charlie"];

Этот синтаксис отлично работает со встроенными типами коллекций, но как насчёт наших типов коллекций? Здесь на помощь приходит атрибут CollectionBuilderAttribute, позволяющий расширить этот современный синтаксис на пользовательские типы.

Пользовательские коллекции
Представьте, что вы создали свой тип коллекции:
public class MyCollection<T> 
{
private readonly List<T> _items;

public MyCollection(ReadOnlySpan<T> items) =>
_items = [.. items];

public IEnumerator<T> GetEnumerator()
=> _items.GetEnumerator();

// другие члены…
}

Раньше вы не могли использовать синтаксис выражений коллекций для этого типа. Вам приходилось использовать старый способ:
var myCol = 
new MyCollection<int>(new[] { 1, 2, 3, 4, 5 });

Либо (что не сильно меняет дело):
var myCol = 
new MyCollection<int>([1, 2, 3, 4, 5]);

Не слишком элегантно.

Атрибут CollectionBuilderAttribute устраняет этот разрыв, сообщая компилятору, как конструировать вашу коллекцию из выражения коллекции:
[CollectionBuilder(typeof(MyCollectionBuilder),
nameof(MyCollectionBuilder.Create))]
public class MyCollection<T>
{
//…
}

public static class MyCollectionBuilder
{
public static MyCollection<T>
Create<T>(ReadOnlySpan<T> items)
=> new([..items]);
}

Теперь мы можем использовать:
MyCollection<int> myCol = [1, 2, 3, 4, 5];

Компилятор автоматически вызовет метод Create, передав ему элементы.

Как это работает
Атрибут принимает два параметра:
1. Тип построителя – тип, содержащий фабричный метод (typeof(MyCollectionBuilder));
2. Имя метода – имя статического метода, создающего экземпляр ("Create").

Метод построителя должен:
- быть статическим;
- принимать либо ReadOnlySpan<T> (предпочтительно), либо T[];
- возвращать экземпляр типа коллекции;
- иметь параметры типа, соответствующие вашей коллекции.

Замечание: также необходимо, чтобы коллекция имела «тип итерации», то есть имела метод GetEnumerator(), возвращающий IEnumerator (или IEnumerator<T>). Можно либо реализовать интерфейс IEnumerable или IEnumerable<T>, либо просто добавить метод GetEnumerator().

Когда всё это реализовано, компилятор может сгенерировать необходимый код для построения вашей коллекции наиболее эффективным способом.

Источник: https://bartwullems.blogspot.com/2025/11/how-to-uninstall-older-net-core-versions.html
  • 👍 25
More from @netdeveloperdiary
  1. Sep 30, 2026Post #3356
  2. Sep 29, 2026Фото 3 (с) Анатолий Кулаков
  3. Sep 29, 2026День 2799. Конференция DotNext 2026. Часть 1 25 и 26 сентября в Москве прошла очередная ко…
  4. Sep 28, 2026День 2798. #Оффтоп Утиная Типизация в C# с Помощью Перехватчиков. Часть 2 Некоторое время…
  5. Sep 27, 2026День 2797. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Окончание Начало Продол…
  6. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →