Пропускает ли тип значения в параметре "out", чтобы переменная была помещена в бокс?

Я знаю, что бокс и распаковка относительно дороги с точки зрения производительности. Мне интересно:

Передаёт ли тип значения параметру out метод вызвать бокс/распаковку переменной (и, следовательно, удар производительности)? Может ли компилятор оптимизировать это?

  int number;
  bool result = Int32.TryParse(value, out number);

Ответы

Ответ 1

Как отмечали другие, здесь нет бокса. Когда вы передаете переменную в качестве аргумента, соответствующего параметру out или ref, то, что вы делаете, делает псевдоним переменной. Вы ничего не делаете со значением переменной. Вы создаете две переменные, представляющие одно и то же место хранения.

Бокс происходит только тогда, когда значение типа значения преобразуется в значение ссылочного типа, и в вашем примере нет никакого преобразования. Тип ссылки должен быть, конечно, System.Object, System.ValueType, System.Enum или любым интерфейсом. Обычно это довольно ясно; там явное или неявное преобразование в коде. Однако могут быть обстоятельства, когда это менее понятно. Например, когда вызывается не переопределенный виртуальный метод базового типа структуры, есть бокс. (Есть также странные ситуации, когда определенные типы ограничений типа могут вызвать неожиданный бокс, но обычно они не возникают на практике.)

Ответ 2

Нет бокса, компилятор использует инструкцию ldloca.s, которая выталкивает ссылку на локальную переменную в стек (http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.ldloca_s (VS.71).aspx)

.method private hidebysig static void Func() cil managed
{
    .maxstack 2
    .locals init (
        [0] int32 num,
        [1] bool flag)
    L_0000: nop 
    L_0001: ldstr "5"
    L_0006: ldloca.s num
    L_0008: call bool [mscorlib]System.Int32::TryParse(string, int32&)
    L_000d: stloc.1 
    L_000e: ret 
}

Ответ 3

Нет, нет бокса (обязательно/участие).

Когда вы вставляете переменную, изменения в экземпляре в штучной упаковке не влияют на оригинал. Но это именно то, что должен делать out.

Компилятор "каким-то образом" создает ссылку на исходную переменную.

Ответ 4

Нет бокса; что делает параметр out, указывает, что номер должен быть назначен внутри метода TryParse. Независимо от этого, он по-прежнему рассматривается как int, а не object.