Список инициализации <int> в С# 3.5

Я могу инициализировать List<int> like new List<int>{1,2,3,4,5}; Однако List<T> не имеет конструктора, который принимает единственный параметр. Поэтому я попытался запустить это через отладчик и, похоже, вызывает метод Add. Итак, как компилятор знает, какой метод вызывать для добавления каждого отдельного элемента.

Это может быть глупый вопрос, но я немного смущен.

Спасибо

Ответы

Ответ 1

Каждый тип, который имеет метод Add и реализует IEnumerable, может быть инициализирован таким образом. Компилятор просто компилирует ваш код так, как если бы вы использовали этот метод Add.

посмотрите здесь

Ответ 2

Это инициализатор коллекции, функция языка С# 3.0. Для этого требуется:

  • тип должен реализовывать IEnumerable (хотя это никогда не используется для инициализации)
  • тип должен иметь хотя бы один метод Add

Он просто вызывает метод Add для каждого термина. Вы также можете использовать кортежи, если Add принимает несколько значений, например словари. Каждый член тогда {key,value}:

new Dictionary<int,string> {{1,"abc"},{2,"def"}};

Пример использования этого для типа на заказ:

class Program
{
    static void Main()
    {
        new Foo { 1, "abc", { 2, "def" } };
    }
}

class Foo : IEnumerable
{
    public void Add(int a) { }
    public void Add(string b) { }
    public void Add(int a, string b) { }
    // must implement this!! (but never called)
    IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); }
}

Ответ 3

Посмотрите на этот метод.

    public void CreateList()
    {
        List<int> list = new List<int> { 1, 2, 3, 4, 5 };
    }

После компиляции это выглядит как MSIL.

.method public hidebysig instance void  CreateList() cil managed
{
  // Code size       50 (0x32)
  .maxstack  2
  .locals init ([0] class [mscorlib]System.Collections.Generic.List`1<int32> list,
           [1] class [mscorlib]System.Collections.Generic.List`1<int32> '<>g__initLocal0')
  IL_0000:  nop
  IL_0001:  newobj     instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor()
  IL_0006:  stloc.1
  IL_0007:  ldloc.1
  IL_0008:  ldc.i4.1
  IL_0009:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
  IL_000e:  nop
  IL_000f:  ldloc.1
  IL_0010:  ldc.i4.2
  IL_0011:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
  IL_0016:  nop
  IL_0017:  ldloc.1
  IL_0018:  ldc.i4.3
  IL_0019:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
  IL_001e:  nop
  IL_001f:  ldloc.1
  IL_0020:  ldc.i4.4
  IL_0021:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
  IL_0026:  nop
  IL_0027:  ldloc.1
  IL_0028:  ldc.i4.5
  IL_0029:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
  IL_002e:  nop
  IL_002f:  ldloc.1
  IL_0030:  stloc.0
  IL_0031:  ret
} // end of method Program::CreateList

Как вы можете заметить, это просто синтаксический сахар, и компилятор заменяет инициализацию последовательными вызовами Add().

Ответ 4

new List{ 1, 2, 3, 4, 5 } - это просто синтаксический "сахар". Под обложками он просто вызывает метод Add для каждого элемента.

Ответ 5

Поскольку new List<int>{1,2,3,4,5} - инициализация массива, я предпочитаю думать, что это работает изнутри по волшебству, так как я не могу повлиять на то, как это происходит. Подумав об этом, он, вероятно, определяет метод по умолчанию для добавления элементов в коллекцию в метаданных, где [] выполняется по индексу, а те, которые реализуют IList, выполняются методом Add.