Подтвердить что ты не робот

Как работает инициализация словаря на С#?

var maxDictionary = new Dictionary<int, double> { { 10, 40000 } };

В приведенном выше коде компилятор использует конструктор? Или компилятор создает KeyValuePair и добавляет в словарь? Я пытаюсь понять, как его интерпретирует компилятор.

4b9b3361

Ответ 1

Да, компилятор использует конструктор без параметров без параметров и затем добавляет все значения, указанные в инициализаторе коллекции, с помощью метода Dictionary.Add. Как указал Джон, ваш код скомпилирован в

Dictionary<int, double> maxDictionary2;
Dictionary<int, double> maxDictionary;

maxDictionary2 = new Dictionary<int, double>();
maxDictionary2.Add(10, 40000.0);
maxDictionary = maxDictionary2;

Сгенерированный IL:

.maxstack 3
.locals init (
     [0] class [mscorlib]Dictionary`2<int32, float64> maxDictionary,
     [1] class [mscorlib]Dictionary`2<int32, float64> maxDictionary2)
L_0000: nop 
L_0001: newobj instance void [mscorlib]Dictionary`2<int32, float64>::.ctor()
L_0006: stloc.1 
L_0007: ldloc.1 
L_0008: ldc.i4.s 10
L_000a: ldc.r8 40000
L_0013: callvirt instance void [mscorlib]Dictionary`2<int32, float64>::Add(!0, !1)
L_0018: nop 
L_0019: ldloc.1 
L_001a: stloc.0 

т.е. созданный словарь, назначенный временной переменной maxDictionary2, заполненной значениями, и только затем ссылка на созданный и заполненный словарь копируется в переменную maxDictionary.

Имейте в виду, что вы можете указать любой другой конструктор, если вы не хотите использовать безпараметрический. Например. вы можете использовать тот, который устанавливает начальную емкость:

var maxDictionary = new Dictionary<int, double>(10) { { 10, 40000 } };

Ответ 2

var maxDictionary = new Dictionary<int, double> { { 10, 40000 } };

Вот сгенерированный IL программы

IL_0001:  newobj      System.Collections.Generic.Dictionary<System.Int32,System.Double>..ctor
IL_0006:  stloc.1     // <>g__initLocal0
IL_0007:  ldloc.1     // <>g__initLocal0
IL_0008:  ldc.i4.s    0A 
IL_000A:  ldc.r8      00 00 00 00 00 88 E3 40 
IL_0013:  callvirt    System.Collections.Generic.Dictionary<System.Int32,System.Double>.Add
IL_0018:  nop         
IL_0019:  ldloc.1     // <>g__initLocal0
IL_001A:  stloc.0     // maxDictionary

Ясно, что он использует беззаметный конструктор и вызывает метод Add. Метка "IL_0013" показывает вызов метода Add

Эквивалентный код С# будет

Dictionary<int, double> maxDictionary;
Dictionary<int, double> temp = new Dictionary<int, double>();
temp.Add(10, 40000.0);
maxDictionary = temp;

Стоит отметить, что компилятор использует переменную temp, я вижу две причины для этого

  • Чтобы убедиться в том, что вы не получаете словарь с половиной выпечки, когда он сталкивается с исключением.
  • Вы не ожидаете, что компилятор прочитает поле только для создания нового экземпляра и назначения. Не правда ли?