Я немного поигрался с классом Эрика Липперта Ref
из здесь . Я заметил в IL, что похоже, что оба анонимных метода использовали один и тот же сгенерированный класс, хотя это означало, что у класса была дополнительная переменная.
Хотя использование только одного нового определения класса кажется несколько разумным, мне это кажется очень странным что создается только один экземпляр c__DisplayClass2
. Похоже, это означает, что оба экземпляра Ref
ссылаются на один и тот же c__DisplayClass2
. Это не означает, что y
не может быть собран до ] vart1
собрано, что может произойти намного позже, чем после возвращения joik
? В конце концов, нет никакой гарантии, что какой-нибудь идиот не напишет функцию (прямо в IL), которая напрямую обращается к y
через vart1
после возвращения joik
. Возможно, это можно было бы сделать даже с помощью отражения вместо сумасшедшего IL.
sealed class Ref
{
public delegate T Func();
private readonly Func getter;
public Ref(Func getter)
{
this.getter = getter;
}
public T Value { get { return getter(); } }
}
static Ref joik()
{
int[] y = new int[50000];
int x = 5;
Ref vart1 = new Ref(delegate() { return x; });
Ref vart2 = new Ref(delegate() { return y; });
return vart1;
}
Запуск IL DASM подтвердил, что vart1
и vart2
оба использовали __ DisplayClass2
, что содержит публичное поле для x и для y. IL joik:
.method private hidebysig static class Program/Ref`1
joik() cil managed
{
// Code size 72 (0x48)
.maxstack 3
.locals init ([0] class Program/Ref`1 vart1,
[1] class Program/Ref`1 vart2,
[2] class Program/'<>c__DisplayClass2' '<>8__locals3',
[3] class Program/Ref`1 CS$1$0000)
IL_0000: newobj instance void Program/'<>c__DisplayClass2'::.ctor()
IL_0005: stloc.2
IL_0006: nop
IL_0007: ldloc.2
IL_0008: ldc.i4 0xc350
IL_000d: newarr [mscorlib]System.Int32
IL_0012: stfld int32[] Program/'<>c__DisplayClass2'::y
IL_0017: ldloc.2
IL_0018: ldc.i4.5
IL_0019: stfld int32 Program/'<>c__DisplayClass2'::x
IL_001e: ldloc.2
IL_001f: ldftn instance int32 Program/'<>c__DisplayClass2'::'b__0'()
IL_0025: newobj instance void class Program/Ref`1/Func`1::.ctor(object,
native int)
IL_002a: newobj instance void class Program/Ref`1::.ctor(class Program/Ref`1/Func`1)
IL_002f: stloc.0
IL_0030: ldloc.2
IL_0031: ldftn instance int32[] Program/'<>c__DisplayClass2'::'b__1'()
IL_0037: newobj instance void class Program/Ref`1/Func`1::.ctor(object,
native int)
IL_003c: newobj instance void class Program/Ref`1::.ctor(class Program/Ref`1/Func`1)
IL_0041: stloc.1
IL_0042: ldloc.0
IL_0043: stloc.3
IL_0044: br.s IL_0046
IL_0046: ldloc.3
IL_0047: ret
} // end of method Program::joik