Patrząc na wyjściu ILDASM, nie może być wyjaśnienie tutaj ...
.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
{
Podczas przeciągania kursora wykonania, to ryzykujemy zgorszenie stos wywołań. Jest tak dlatego, że przeciągnięcie kursora dosłownie pomija te linie. Podczas uruchamiania w debugerze, po naciśnięciu klawisza F10, kursor zatrzymuje się przed uruchomieniem procedury Main
przed próbą. Jeśli przeciągnij kursor do utworzenia tablicy, jesteś pomijanie tej zabawy wiersz:
IL_0001: newobj instance void Test.Program/'<>c__DisplayClass1'::.ctor()
który tworzy instancję klasy Program
. Klasa program jest następnie wykorzystywany później tutaj:
IL_0019: stfld string[] Test.Program/'<>c__DisplayClass1'::one
Która bo go pominąć, nie stworzył tego obiektu, więc masz NullReferenceException
podczas biegu.
Dlaczego ludzie nie mogą tego odtworzyć na VS2012, nie jestem pewien. Być może kompilator wyprowadza różne IL, ale jest to daleko, jak mogę wymyślić przy użyciu VS2013 Ultimate i C# 4.5.
Co ciekawe, kiedy zakomentuj try/catch, początek programu w IL wygląda tak:
.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
którym można zobaczyć pierwszą linię w rutynę tworzy obiekt Program
. Dlaczego kompilator zdecydował się umieścić tę linię wewnątrz try/catch jest poza mną.
EDIT
Kopiąc głębiej, zmieniając swój program do tego:
private static void Main(string[] args)
{
string[] one;
try
{
// 1. Hit F10 to step into debugging.
one = new string[] { "1" }; //2. Drag arrow to this
// 3. Hit f5.
Enumerable.Range(1, 1)
.Where(x => one.Contains(x.ToString()));
}
catch (Exception exception)
{
Console.Write("BOOM!");
}
}
Wyniki w kod działa. Badając IL, można zobaczyć, że tworzenie instancji został przeniesiony poza Spróbuj:
.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
{
Kompilator był na tyle miły, aby przesunąć utworzenie tablicy ciągów spoza starają się wewnątrz próbie, więc pomijanie tej linii nadal daje prawidłowy obiekt. Kod działa, więc domyślam się, że NullReferenceException
jest instancją klasy Program
.
Wyjątek to "Odwołanie do obiektu nie jest ustawione na wystąpienie obiektu". – Robino
Powinieneś dodać to do pytania, a nie w komentarzu. – juharr
Nie można odtworzyć. – Habib