День двести пятидесятый. #ЗаметкиНаПолях

Использование методов расширения в инициализаторах коллекций

Для использования инициализатора коллекции необходимы два условия:

- Тип должен реализовывать IEnumerable. Это раздражающее ограничение. Иногда приходится реализовывать IEnumerable исключительно для того, чтобы использовать тип в инициализаторах коллекций.

- Должен быть подходящий метод Add для каждого элемента в инициализаторе коллекции. Предполагается, что любые элементы, которые не находятся в фигурных скобках, соответствуют вызовам метода Add с одним аргументом. Когда требуется несколько аргументов, они должны быть в фигурных скобках. Например:

List<string> strings = new List<string> { 10, "hello", { 20, 3 } };

Эквивалентно:

List<string> strings = new List<string>();

strings.Add(10);

strings.Add("hello");

strings.Add(20, 3);

Далее для определения, что значит каждый вызов, применяется стандартное разрешение перегрузки методов. С обычным List<T> этот код не скомпилируется. Но можно добавить метод расширения:

public static void Add(

this List<string> list, int value, int count = 1)

{

list.AddRange(Enumerable.Repeat(value.ToString(), count));

}

Этот метод добавляет значение первого аргумента столько раз, сколько указано во втором аргументе. Таким образом список примет вид: "10", "hello", "20", "20", "20".



Варианты использования:

1. Создание сигнатур метода Add общего назначения. Например, инициализация коллекцией:

public static void Add<T>(this List<T> list, IEnumerable<T> collection)

{

list.AddRange(collection);

}

Применение (контакты человека инициализируются коллекцией людей из Москвы):

Person jon = new Person

{

Name = "Jon",

Contacts = { allContacts.Where(c => c.Town == "Moscow") }

};

2. Создание специализированных сигнатур метода Add. Например, добавление в словарь объектов (людей) с ключом в виде одного из свойств (имя):

public static void Add(

this Dictionary<string, Person> dictionary, Person person)

{

dictionary.Add(person.Name, person);

}

Применение:

var dictionary = new Dictionary<string, Person>

{

{ new Person { Name = "Jon", … } },

{ new Person { Name = "Holly", … } }

};



Источник: Jon Skeet “C# In Depth”. 4th ed – Manning Publications Co, 2019. Глава 10.