Я немного играл с классом Eric Lippert Ref<T>
из здесь. Я заметил в IL, что похоже, что оба анонимных метода использовали один и тот же сгенерированный класс, хотя это означало, что у класса была дополнительная переменная.
При использовании только одного определения нового класса кажется несколько разумным, мне кажется очень странным, что создается только один экземпляр <>c__DisplayClass2
. Это означает, что оба экземпляра Ref<T>
ссылаются на один и тот же <>c__DisplayClass2
Не означает ли это, что y
невозможно собрать до тех пор, пока vart1
не будет собрано, что может произойти намного позже, чем после возврата joik
? В конце концов, нет никакой гарантии, что какой-то идиот не будет писать функцию (непосредственно в IL), которая напрямую обращается к y
через vart1
aftrer joik
. Возможно, это может быть даже сделано с отражением, а не через сумасшедший ИЛ.
sealed class Ref<T>
{
public delegate T Func<T>();
private readonly Func<T> getter;
public Ref(Func<T> getter)
{
this.getter = getter;
}
public T Value { get { return getter(); } }
}
static Ref<int> joik()
{
int[] y = new int[50000];
int x = 5;
Ref<int> vart1 = new Ref<int>(delegate() { return x; });
Ref<int[]> vart2 = new Ref<int[]>(delegate() { return y; });
return vart1;
}
Запуск IL DASM подтвердил, что vart1
и vart2
оба использовали <>__DisplayClass2
, который содержал общедоступное поле для x и y. ИЛ от joik:
.method private hidebysig static class Program/Ref`1<int32>
joik() cil managed
{
// Code size 72 (0x48)
.maxstack 3
.locals init ([0] class Program/Ref`1<int32> vart1,
[1] class Program/Ref`1<int32[]> vart2,
[2] class Program/'<>c__DisplayClass2' '<>8__locals3',
[3] class Program/Ref`1<int32> 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'::'<joik>b__0'()
IL_0025: newobj instance void class Program/Ref`1/Func`1<int32,int32>::.ctor(object,
native int)
IL_002a: newobj instance void class Program/Ref`1<int32>::.ctor(class Program/Ref`1/Func`1<!0,!0>)
IL_002f: stloc.0
IL_0030: ldloc.2
IL_0031: ldftn instance int32[] Program/'<>c__DisplayClass2'::'<joik>b__1'()
IL_0037: newobj instance void class Program/Ref`1/Func`1<int32[],int32[]>::.ctor(object,
native int)
IL_003c: newobj instance void class Program/Ref`1<int32[]>::.ctor(class Program/Ref`1/Func`1<!0,!0>)
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