[英]Debugger stepping in if statement and lambda expression
使用以下代碼作為示例:
if (true)
{
string foo = null;
List<string> bar = new List<string>
{
"test"
};
bar.Any(t => t == foo);
}
如果我以常規方式運行此程序(沒有斷點或任何其他中斷),一切都可以正常運行,無異常或錯誤(正如您所期望的那樣)。
現在,如果我在if語句上放置一個斷點並將光標移動到大括號,如下圖所示(使用我的鼠標,不使用F10,所以跳過if(true)
語句):
當調試器執行語句string foo = null
時,我得到類型System.NullReferenceException
的異常
它似乎與變量foo
在if
語句中的lambda表達式中使用的事實有關。 我已經在Visual Studio 2012和2013(專業版和終極版)上測試並重現了這一點。
為什么會發生這種情況的任何想法?
推測你正在跳過閉包生成的評論是正確的。 移動指令指針時,不保證C#程序具有任何特定行為。 如果你這樣做會傷害,不要這樣做。
實際上這是一個小謊言。 有保證。 例如,您可以保證在可驗證的程序中這樣做不會破壞clr的內部數據結構。 您可以保證這樣做不會使堆棧錯位。 等等。 但是,您的數據結構不能表達或暗示任何保證! 您將指令指針移動到您的危險之中。
Eric的回答和評論已經描述了為什么它會發生。 我想強調在這個特殊情況下發生的事情。
這是生成的IL:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 3
.locals init (
[0] class [mscorlib]System.Collections.Generic.List`1<string> bar,
[1] class [mscorlib]System.Collections.Generic.List`1<string> <>g__initLocal0,
[2] class StackOverflow.Program/<>c__DisplayClass2 CS$<>8__locals3,
[3] bool CS$4$0000)
L_0000: nop
L_0001: ldc.i4.0
L_0002: stloc.3
L_0003: newobj instance void StackOverflow.Program/<>c__DisplayClass2::.ctor()
L_0008: stloc.2
L_0009: nop
L_000a: ldloc.2
L_000b: ldnull
L_000c: stfld string StackOverflow.Program/<>c__DisplayClass2::foo
L_0011: newobj instance void [mscorlib]System.Collections.Generic.List`1<string>::.ctor()
L_0016: stloc.1
L_0017: ldloc.1
L_0018: ldstr "test"
L_001d: callvirt instance void [mscorlib]System.Collections.Generic.List`1<string>::Add(!0)
L_0022: nop
L_0023: ldloc.1
L_0024: stloc.0
L_0025: ldloc.0
L_0026: ldloc.2
L_0027: ldftn instance bool StackOverflow.Program/<>c__DisplayClass2::<Main>b__1(string)
L_002d: newobj instance void [mscorlib]System.Func`2<string, bool>::.ctor(object, native int)
L_0032: call bool [System.Core]System.Linq.Enumerable::Any<string>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [mscorlib]System.Func`2<!!0, bool>)
L_0037: pop
L_0038: nop
L_0039: ret
}
注意L_0003
行。 它調用ctor為自動生成的c__DisplayClass2
類,它保存foo
字段,因為你在lambda中使用它。 所以NullReferenceException
發生是因為你的跳過類初始化,但是你在一行L_000c
上分配實例的字段foo
。
太糟糕了,沒有簡單的方法來調試IL級別來驗證這一點,但我們可以調試JITed程序(Debug - > Disassembly)
這是你的第一個斷點:
然后光標移動后:
其中一個滑雪呼叫教練必須從L_0003
打電話給ctor。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.