It is compiler bug and very weird. Let me explain details. I would be really happy if some experts clarify it.
Yes, it is incorrect to capture this in ctor, but the situation gets hot because this was used inside anonymous delegate. Normally, if anonymous delegate doesn't have closure (doesn't capture outer variables) it is implemented by compiler as static method of same class. It happened here. But let's take a look in IL code generated of that static method:
.method private hidebysig static bool <.ctor>b__0() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()
.maxstack 1
.locals init (
[0] bool CS$1$0000)
L_0000: nop
L_0001: ldloc.0
L_0002: call instance bool ConsoleApplication15.Derived::MyValue()
L_0007: stloc.0
L_0008: br.s L_000a
L_000a: ldloc.0
L_000b: ret
}
did you see that? take closer look at line L_0002 and line L_0001. There are two extremely strange things:
- We tried to call method
MyValue against bool!
- The method was called as
call but it is not static, C# compiler usually call instance methods with callvirt! If the callvirt was used this call would fail, because callvirt checks for this == null.
Now let's break it. Let's introduce closure and change code to:
public Derived(bool myValue) : base(delegate() { return myValue ^ this.MyValue(); }) {
this.myValue = myValue;
}
And now everything is fine! No NRE! Anonymous class was generated and it's fields capture the closure. In this case correct IL is generated:
.method public hidebysig instance bool <.ctor>b__0() cil managed
{
.maxstack 2
.locals init (
[0] bool CS$1$0000)
L_0000: nop
L_0001: ldarg.0
L_0002: ldfld bool ConsoleApplication15.Derived/<>c__DisplayClass1::myValue
L_0007: ldarg.0
L_0008: ldfld class ConsoleApplication15.Derived ConsoleApplication15.Derived/<>c__DisplayClass1::<>4__this
L_000d: call instance bool ConsoleApplication15.Derived::MyValue()
L_0012: xor
L_0013: stloc.0
L_0014: br.s L_0016
L_0016: ldloc.0
L_0017: ret
}
Method is called against closured this. (but still with call instance, hmm)