VS踩坑記錄:C#中屬性get塊含有寫入代碼,斷點調試時讀取屬性get塊一樣會造成寫入效果

我很多時候貪圖方便,喜歡在屬性的get塊中加入對其他變量修改的操作……如果你跟我有一樣的習慣,而且正在使用VisualStudio斷點調試,那就要小心了= =

最近在整一個鏈表,我希望可以實現取出鏈表中第一個結點(head)。由於平時的壞習慣,沒有用函數,而是直接用了屬性的get塊實現:

然後在鏈表測試的時候,出現了錯誤(事實上我的錯誤是別的錯誤,但是這導致我使用斷點調試發現了本文要討論的蛇皮錯誤)於是我進入斷點調試模式……監控變量。
然後我發現神奇的事情發生了:head前一秒還正在,後一秒就消失!!!
比如這樣:

前一秒還是head != null的
然而後一秒……我甚至沒有執行下一步,就再看了一次

好的head已經變成null了,只因在人羣中多看了它一眼

???
我當場就日了狗了,每次變成null的時間點還不一樣,但都是在我查看之後沒了!
當時完全不知道是什麼問題
第二天逐個排查,最後發現在刪除了PopFirstNode屬性之後就不會出現這個問題(沒想到竟然是這個)
而且非斷點調試也不會出現這個問題
那問題大概就明朗了:
斷點調試中可以看到代碼中的變量值,然而屬性值是怎麼看的呢?到這裏,其實已經很顯然是通過get塊讀取的了。也正是因爲通過它是通過get塊讀取了(PopFirstNode屬性的)變量值,它同樣執行了其中的變量修改代碼,於是乎head就理所當然變成下一個元素,也就是null了……也說明爲什麼第一次看還是在的,然而第二次再看就突然變成null了。
其實就是VS斷點調試時讀取屬性值會隱式訪問屬性中的get塊(沒錯,這個過程本身是不會觸發斷點的,所以我們能感覺到的就只是莫名其妙出現了問題)

同樣在另一篇文章也看到類似的描述:
C#斷點調試時屬性get塊邏輯執行多次

但是遺憾的是,我把該項設置反選後並無事發生……還是能讀取屬性值,也還是能刪掉我的head
不過問題不大了,只是沒想到自己的習慣居然會帶來這麼難找的bug

所以如果你在使用斷點調試(vs的,其他的不知道會不會有這種問題)請注意:
①屬性get塊儘量不要有寫入操作
②如果真的改不了習慣,你要清楚意識到這個問題!並且在調試時不要在能讀取屬性的地方加入斷點,可以考慮直接控制檯print變量(不要用屬性喔 否則還是會訪問get塊)

哎 又被莫名其妙的小問題耗了一天 歡樂時光又要結束了 媽耶

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章