Its time to bite the bullet. As MS throws more and more functional programming techniques at us, and we all start tossing lambdas around, and passing functions as arguments to functions, and the compiler starts auto-generating more and more of our code for us, and Reflector starts getting its C# interpretation of the auto-generated code "wronger and wronger", I find my self writing more and more code I can't understand - without understanding IL.
Can anyone recommend some essential IL for dummies resources? Books, walk-throughs, references, videos, anything...
Here's a couple examples of what I mean.
Why does:
Code:
var actionList = newList<Func<int>>();
foreach (var value inEnumerable.Range(0, 10))
{
actionList.Add(() => value);
}
actionList.ForEach(func => Console.Write("{0} ", func()));
print '9 9 9 9 9 9 9 9 9 9' while
Code:
var actionList = newList<Func<int>>();
foreach (var value inEnumerable.Range(0, 10))
{
int myValue = value;
actionList.Add(() => myValue);
}
actionList.ForEach(func => Console.Write("{0} ", func()));
prints '0 1 2 3 4 5 6 7 8 9'.
Reflector's C# interpretation is worthless. But the IL shows that the auto-generated class that captures the local variable gets its constructor called once in the first example (the local variable instance is reused), and multiple times in the second example (a new instance of the captured variable is created).
Or iterator blocks (state machines):
Code:
staticIEnumerator<int> GetCounter()
{
for (int count = 0; count < 10; count++)
{
yield return count;
}
}
gets "compiler-generated" as:
Code:
privatebool MoveNext()
{
switch (_state)
{
case 0:
_state = -1;
_count_1 = 0;
while (_count < 10)
{
_current = _count;
_state = 1;
return true;
Label_0046:
_state = -1;
_count++;
}
break;
case 1:
goto Label_0046;
}
return false;
}
which is illegal C# 'cause the label is out of the 'goto' statements scope, so to understand whats happening we need:
Code:
publicbool MoveNext()
{
switch (_state)
{
case 0:
_state = -1;
_count = 0;
goto endLoop;
loop:
_current = _count;
_state = 1;
return true;
Label_0046:
_state = -1;
_count++;
endLoop:
if (this._count < 10)
goto loop;
break;
case 1:
goto Label_0046;
}
return false;
}
'cus IL doesn't know about 'while' loops.
That sort of thing. Stuff thats only understandable if you understand IL, which I'm seeing more and more of.
Bob