2010-05-27 35 views
16

對象未設置爲一個對象的實例」「對象引用未設置爲對象實例」:爲什麼.NET不能顯示更多詳細信息?

爲什麼例外而不是還顯示名稱的對象引用字段的,或至少它的類型?

這可能是.NET中最常見的運行時錯誤之一。雖然System.Exception有一個堆棧跟蹤,但沒有其他有用的細節。

在一年的時間裏,我花了幾個小時篩選堆棧跟蹤(通常在我沒有寫的代碼中),希望從「.pdb」文件中找到行號,然後在代碼中找到該行,並且即使這樣,線上的哪個引用爲空也不明顯。具有參考字段的名稱將非常方便。

如果System.ArgumentNullException實例可以顯示名稱的方法參數的(「值不能爲空參數名:」),那麼肯定System.NullReferenceException情況下可以包括空的名字字段(或其包含的集合)。

+0

那裏有問題嗎? – Nix 2010-05-27 02:25:51

+0

@Nix:「爲什麼異常不會顯示對象引用字段的名稱,或者至少是它的類型?」 – 2010-05-27 02:28:00

+1

我不得不讓你高興起來,因爲那個該死的問題一直讓我瘋狂! :) – Dave 2010-05-27 02:37:47

回答

2

這已經涵蓋在這裏:Detecting what the target object is when NullReferenceException is thrown

這裏:Why can't a null-reference exception name the object that has a null reference?

究其原因主要是使運行時有遇到NRE時不知道。我猜測它必須回調調用堆棧並通過分析樹,這將非常昂貴。

+0

感謝(第一個)鏈接。這個問題更多地涉及目標對象(或缺少目標對象)以及如何調試問題。 對於確定NRE源代碼的昂貴處理,尤其是對於調試版本而言,您可能是正確的,但與所涉及的調試工作相比,這將是微不足道的。 – 2010-05-27 02:48:33

0

我沒有發現這個很難處理的異常!

如果我知道行號。我只是在這一行插入一個斷點,運行應用程序到這一行,並且當調試器停止時,我將每個變量/對象懸停在行中,並感謝Visual Studio,它向我顯示了它們的值。

此外,我發現汽車窗口在這種情況下非常有用,但我上面描述的過程很快就解決了我的問題。

+0

謝謝,但我知道如何在VS中進行調試;那不是重點。我想知道爲什麼.NET不能用NullReferenceExceptions更明確。如果我知道未設置字段的名稱,通常我甚至不需要調試代碼。 – 2010-05-27 03:06:04

7

ArgumentNullExceptionNullReferenceException之間的區別是,ArgumentNullException總是明確地拋出像這樣:

if (parameter == null) 
    throw new ArgumentNullException("parameter"); 

有一個快速瀏覽一下ILDASM輸出,局部變量確實存在函數的IL內。但是,仍然沒有API以編程方式檢索這些名稱。我的理解是,這將是相當複雜的,因爲你基本上需要構建一個代表函數的解析樹,這個函數包含了作用域,變量,語句等。

它變得更加複雜,它不僅僅是簡單的變量NullReferenceException,但函數調用的結果,屬性或表達式。我可以相當快地相當複雜。

想象一下:

internalObject.OtherProperty = myObject.GetOtherObject().ThirdObject.SomeProperty == "value" 
? myObject.OtherProperty 
: myObject.GetSomethingElse(); 

有多個故障點的存在,並建立代表什麼是真正null可能會非常棘手的字符串。

+0

變量名稱在IL中消失並不是真的。在程序集上運行ILDasm或Reflector並查看。 – 2010-05-27 03:09:08

+1

我剛剛做到了,你是對的。 – 2010-05-27 03:13:32

+1

感謝您的最新答案及其見解 - 您對某些NullReferenceExceptions(我的+1)的複雜來源提出了一個非常好的觀點。對於簡單的空字段引用異常來說,即使沒有外部API,.NET運行時似乎也可以提供更多的細節。在更復雜的例子中,仍然沒有足夠的證據來證明爲什麼運行時不能明確地標識「myObject」,「myObject.GetOtherObject()返回值」或「myObject.GetOtherObject()。ThirdObject」作爲NullReferenceException源。如果它需要一個解析樹,那就這樣吧! – 2010-05-27 05:48:49

1

儘管MSIL代碼中可能存在變量名稱和類型,但在MSIL處於JITT時它不會存在於本機代碼中。

在JITting期間將這種檢查添加到本機代碼是非常低效的 - 實質上每當指針被解引用時都會有開銷。

+0

+1爲進一步研究一個有趣的點。在不瞭解PDB文件以及它們在運行時如何使用的情況下,出現故障的行和列號與JITed代碼以某種方式相關聯,所以其他信息可能也會如此,特別是對於Debug版本。 – 2010-05-27 18:03:07

相關問題