c# - Discrete Anonymous methods sharing a class? -
i playing bit eric lippert's ref<t>
class here. noticed in il looked both anonymous methods using same generated class, though meant class had variable.
while using 1 new class definition seems reasonable, strikes me odd 1 instance of <>c__displayclass2
created. seems imply both instances of ref<t>
referencing same <>c__displayclass2
doesn't mean y
cannot collected until vart1
collected, may happen later after joik
returns? after all, there no guarantee idiot won't write function (directly in il) directly accesses y
through vart1
aftrer joik
returns. maybe done reflection instead of via crazy il.
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 { { 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; }
running il dasm confirmed vart1
, vart2
both used <>__displayclass2
, contained public field x , y. il of 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
yes, ms implementation of anonymous methods creates 1 hidden class per level of scope needs capture variables from, , captures all relevant variables scope. believe done sake of simplicity, can indeed increase lifetime of objects unnecessarily.
it more elegant each anonymous method only capture variables interested in. however, make life considerably more complicated... if 1 anonymous method captured x
, y
, 1 captured x
, 1 captured y
, you'd need 3 classes: 1 capturing x
, 1 capturing y
, , 1 composing 2 (but not having 2 variables). tricky bit single variable instantiation, variable needs live in 1 place refers sees same value, whatever changes it.
this doesn't violate spec in way, considered unfortunate - don't know whether it's bitten people in real life, it's possible.
the news if c# team decide improve this, should able in entirely backwardly compatible way, unless muppets relying on lifetimes being extended unnecessarily.
Comments
Post a Comment