2013-03-19 30 views
0

在VS2010中調試C#代碼時,我測試了我無法解釋的奇怪行爲。 與下面的非常簡化的代碼:C#範圍和visual studio調試

public void Go() 
    { 
     var test = new Random().Next(10) % 2 == 0; // Simulate various cases 

     var qry = new[] { "bla", "ble", "bli", }.ToList(); // Get whole list   

     //string myString; // If declare out of scope OK 
     if (test) // BreakPoint here and dragNDrop on next line 
     { 
      var myString = "bli"; // declare and instanciate in scope => NullReferenceException 

      qry = qry.Where(item => item == myString).ToList(); // filter the list 
     } 
    } 

當我嘗試踏入如果範圍而不與小鼠測試測試值,則的myString不能實例化與扔一個的NullReferenceException。 要獲得「函數式」代碼,我只需將myString聲明爲範圍外。 我不明白爲什麼VS不能讓我跨過if測試,如果有人能解釋我這個奇怪的異常,我會很高興。 由於

編輯: 兩個IL代碼的比較之後(取決於其中的myString聲明制)我可以看到,VS「不能」上產生的隱藏類和的分配執行指令newobj字符串值在空值上生成。在「超出範圍」的聲明版本中,指令是從該方法的開始進行的。

ILCode(inscope):

IL_0041: brtrue.s IL_006e // if (test) 
IL_0043: newobj  instance void ConsoleApplication5.BreakPointTest/'<>c__DisplayClass1'::.ctor() 
IL_0048: stloc.2 
IL_0049: nop 
IL_004a: ldloc.2  
IL_004b: ldstr  "bli" 
IL_0050: stfld  string ConsoleApplication5.BreakPointTest/'<>c__DisplayClass1'::myString 

我認爲,在NOP/ldloc.2指令pointeur完成的跳躍,而 「忘記」 了c__DisplayClass1的instanciation。

+0

你是否正在建造發佈模式?發佈模式下的編譯器優化可以爲代碼做些事情,使調試體驗與您在代碼中看到的內容有點不一致。 – jlew 2013-03-19 11:36:47

+0

我試過這段代碼(在調試器下),它對我來說都工作得很好。 – 2013-03-19 11:37:11

+0

和指令指針的移動一起工作嗎? – user2186214 2013-03-19 12:50:56

回答

0

這看起來像一個調試器問題。但請注意,生成的代碼完全不像您所寫的代碼。您在lambda表達式中使用myString,因此編譯器創建了一個存儲對myString的引用的隱藏類。當您拖動指令指針時,可能會跳過此類的必要初始化,因爲它們未在源中表示。

作爲一個想法,試着在「if」之後的左括號處拖動指令指針。

+0

感謝您的回覆。 – user2186214 2013-03-19 12:39:53

+0

不好意思,這是我的第一個問題......(輸入鍵......)。我建立在調試模式沒有優化,當我拖動只是在開放括號:相同的結果。 @Alex:你應該對代表lambda的隱藏類進行初始化。我會在這個方向上搜索,因爲我不太瞭解內涵。 – user2186214 2013-03-19 12:47:28