Looking at ILDASM's conclusion, there might be an explanation ...
.locals init ([0] class Test.Program/'<>c__DisplayClass1' 'CS$<>8__locals2', [1] class [mscorlib]System.Exception exception, [2] string[] CS$0$0000) IL_0000: nop .try { IL_0001: newobj instance void Test.Program/'<>c__DisplayClass1'::.ctor() IL_0006: stloc.0 IL_0007: nop IL_0008: ldloc.0 IL_0009: ldc.i4.1 IL_000a: newarr [mscorlib]System.String IL_000f: stloc.2 IL_0010: ldloc.2 IL_0011: ldc.i4.0 IL_0012: ldstr "1" IL_0017: stelem.ref IL_0018: ldloc.2 IL_0019: stfld string[] Test.Program/'<>c__DisplayClass1'::one IL_001e: ldc.i4.1 IL_001f: ldc.i4.1 IL_0020: call class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> [System.Core]System.Linq.Enumerable::Range(int32, int32) IL_0025: ldloc.0 IL_0026: ldftn instance bool Test.Program/'<>c__DisplayClass1'::'<Main>b__0'(int32) IL_002c: newobj instance void class [mscorlib]System.Func`2<int32,bool>::.ctor(object, native int) IL_0031: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [System.Core]System.Linq.Enumerable::Where<int32>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [mscorlib]System.Func`2<!!0,bool>) IL_0036: pop IL_0037: nop IL_0038: leave.s IL_004a } // end .try catch [mscorlib]System.Exception {
When you drag the execution cursor, you run the risk of damaging the call stack. This is because dragging the cursor literally skips these lines. When starting in the debugger after pressing F10, the cursor stops at the beginning of the Main procedure before trying. If you drag to create an array, you will skip this line:
IL_0001: newobj instance void Test.Program/'<>c__DisplayClass1'::.ctor()
Creates an instance of the Program class. Then the following class of the program is used:
IL_0019: stfld string[] Test.Program/'<>c__DisplayClass1'::one
That due to the fact that you missed it, you did not create this object, so when you start, you get a NullReferenceException .
Why people cannot reproduce this on VS2012, I'm not sure. It may be that the compiler outputs different ILs, but this is far, since I can come up with VS2013 Ultimate and C # 4.5.
Interestingly, when you comment on try / catch, the start of a program in IL looks like this:
.locals init ([0] class Test.Program/'<>c__DisplayClass1' 'CS$<>8__locals2', [1] string[] CS$0$0000) IL_0000: newobj instance void Test.Program/'<>c__DisplayClass1'::.ctor() IL_0005: stloc.0
What you see the first line in the routine, creates a Program object. Why did the compiler decide to put this line inside try / catch outside of me.
EDIT
Digging a little deeper, changing your program to this:
private static void Main(string[] args) { string[] one; try {
Results in working code. After examining IL, you will see that instantiation has been moved outside of try:
.locals init ([0] class [mscorlib]System.Exception exception, [1] class [mscorlib]System.Func`2<int32,bool> 'CS$<>9__CachedAnonymousMethodDelegate1', [2] class Test.Program/'<>c__DisplayClass2' 'CS$<>8__locals3', [3] string[] CS$0$0000) IL_0000: ldnull IL_0001: stloc.1 IL_0002: newobj instance void Test.Program/'<>c__DisplayClass2'::.ctor() IL_0007: stloc.2 IL_0008: nop .try {
The compiler was good enough to move the creation of an array of strings due to an attempt to try inside try, so skipping this string still leads to a valid object. The code works, so I assume that the NullReferenceException indeed an instance of the Program class.