Home >> Blog >> object reference not set to an instance of an object - 什麼是 NullReferenceException?你調用的對像是空的
object reference not set to an instance of an object - 什麼是 NullReferenceException?object reference not 的解釋
“你調用的對像是空的。” 當他們還是初學者 C#/.NET 程式設計師時,那些從未與此錯誤消息鬥爭過的人投下第一塊石頭。
當您收到 NullReferenceException 時,就會出現這個臭名昭著且可怕的錯誤消息。當您嘗試訪問當前持有空引用的變量上的成員(例如,方法或屬性)時,將引發此異常。
但是什麼是空引用?首先什麼是“參考”?如何阻止 NullReferenceException 在程式碼中發生?這就是我們將在今天的帖子中介紹的內容。
我們將從基礎開始,簡要說明 C#/.NET 中的引用。之後,您將了解什麼是空引用。在這一點上,你已經看到了整個畫面的一半。
經過這一輪的理論定義,我們將進入更實際的問題,教你如何在實踐中避免 NullReferenceException。讓我們深入挖掘。
什麼是參考?
我們已經知道 NullReferenceException 是由空引用引起的。但是什麼是空引用?它與非空引用有何不同?
在 .NET 中,您可以將數據類型分為兩類:值類型和引用類型。如果您有一個值類型的變量,它會存儲值本身。另一方面,引用類型變量不保存值本身。它們持有指向對像在內存中的位置的引用。
如果它可以幫助您更好地可視化它,您可以將參考視為指向網頁的鏈接,或指向計算機上文件的快捷方式。諸如 int(和其他數字基本類型)、DateTime 和 boolean 之類的類型是值類型。也就是說,結構是值類型。類是引用類型。
因此,引用是引用類型的變量所包含的內容。但是,這些變量可以指向“無”,這就是我們所說的空引用:不指向任何對象的引用。當您嘗試在所述變量上調用方法或其他成員時,您會得到 NullReferenceException。
<< 空引用錯誤佔所有應用程序錯誤的很大比例。>>
了解 NullReferenceException
空引用錯誤佔所有應用程序錯誤的很大比例。它們通常是由於沒有添加額外的邏輯來確保對像在使用它們之前具有有效值而導致的非常簡單的問題。以下是避免 NullReferenceException 的一些方法。
如果傳入的變量“text”為空,以下程式碼將拋出 NullReferenceException。您不能在空字符串上調用 ToUpper()。
公共無效我的方法(字符串文本)
{
//如果 text == null 則拋出異常
if (text.ToUpper() == “Hello World”)
{
//做一點事
}
}
你也可以有空引用異常,因為任何類型的對像都是空的。例如,在下面的程式碼中,SqlCommand 對像從未被初始化。不運行 SQL 查詢對您的應用程序來說將是一個嚴重的問題。空字符串可能是您忽略並繼續前進的內容。其他時候,比如 SqlCommand,它可能是一個你不想忽略的致命問題。
//例外!你調用的對像是空的
command.ExecuteNonQuery();
使用 Null 條件運算符避免 NullReferenceExceptions
C# 中最好的新增功能之一是空條件運算符。您可以使用“?”,而不是進行大量的“變量!= null”類型檢查。並且您的程式碼將短路並返回 null 而不是拋出異常。通過下面的一些示例,這將更有意義:
文本?.ToUpper(); //從前面的例子,將返回null
詮釋?長度=客戶列表?。長度;// 如果 customerList 為 null,則為 null
客戶至上 = customerList?[0]; // 如果 customerList 為 null,則為 null
詮釋?count = customerList?[0]?.Orders?.Count(); // 如果 customerList、第一個客戶或 Orders 為 null,則為 null
使用 Null 合併來避免 NullReferenceExceptions
另一個很棒的功能是空合併,即“??” 操作員。它非常適合為 null 的變量提供默認值。它適用於所有可為空的數據類型。
以下程式碼在沒有空值合併的情況下引發異常。添加“?? new List
列表<字符串> 值 = null;
foreach (var value in values ?? new List
{
Console.WriteLine(值);
}
導致問題的空值的簡單示例
一些最常見的原因是設置、數據庫調用或 API 類型調用未返回預期值。例如,您向數據庫中添加了一個新字段,並且不為每條記錄填充默認值。隨機查詢記錄,並且程式碼沒有考慮到該新字段為空。KA-BOOM:對象引用未設置為對象的實例。
編程的黃金法則
多年來,我一直對我的團隊說一句話。我稱之為編程的黃金法則。我認為每個新程式設計師都需要一個紋身來說明這一點。
如果它可以為空,它將為空”
好消息是,可以通過添加額外的邏輯和程式碼來避免很多空引用錯誤,以確保在嘗試使用對象之前不為空。開發人員應該始終假設一切都是無效的,並且在他們的程式碼中非常防禦。假裝每個數據庫調用都會失敗,每個字段都會有混亂的數據。良好的異常處理最佳實踐至關重要。
防止空引用異常的提示
- 用有效值初始化變量。
- 如果變量可以為null,則檢查null並適當處理
- 使用“?” 盡可能在方法上操作。stringvar?.ToUpper();
- 使用 Resharper 等工具來幫助指出潛在的空引用異常
使用 C# 8.0 的可空類型避免 NullReferenceException
空引用錯誤的主要原因之一是在 C 中每個引用類型對像都可以始終為空。如果您,開發人員,有權說:“我希望這個字符串永遠不會為空”怎麼辦?更好的是,如果這個決定是由編譯器本身強制執行的,防止您和其他開發人員意外地將 null 分配給所述變量怎麼辦?聽起來不錯?那麼,好消息是:這是 C# 第八版的一個真正特性,毫不奇怪,稱為可空類型。
<< 該功能以一種巧妙而強大的方式工作。>>
該功能以一種巧妙而強大的方式工作。它將引用類型重新定義為默認情況下不可為空——正如許多人認為它們從一開始就應該如此。然後,它添加了一種新的語法,允許您定義可為空的變量(雖然它並不是真正的新語法,因為它與多年來用於可空值類型的語法相同。)
為了更好地理解,請看以下示例:
靜態 int 添加(字符串數字)
{
返回 numbers.Split(“,”).Select(int.Parse).Sum();
}
在 C# 8.0 之前的版本中,上面的程式碼是危險的。numbers 變量可能為 null,這會在嘗試使用 Split 方法時導致 NullReferenceException。
使用 C# 8.0 可為空的引用類型功能,您會很安全。該變量永遠不能為空,並且對 Split 方法的調用永遠不會拋出。將 null 傳遞給 Add 方法的任何嘗試都將導致編譯錯誤。
但是,如果您想允許數字為空怎麼辦?在這種情況下,您只需在類型名稱後添加一個問號:
靜態 int 添加(字符串?數字)
{
返回 numbers.Split(“,”).Select(int.Parse).Sum();
}
現在情況發生了巨大變化。由於數字現在可以為空,編譯器將提示您檢查變量的值,並發出警告(您可以將警告轉換為編譯器錯誤,以提高安全性):
編譯器讓我知道“數字”可以為空。可能的解決方案包括:
- 使用 if 語句確保變量具有有效引用
- 在調用 Split 方法時使用已經提到的空合併運算符
- 通過刪除問號使“數字”變量再次不可為空
- 禁止給我們警告的規則(這會破壞整個目的,但是嘿,這是一種選擇。)
請記住,此功能是可選的。也就是說,默認情況下它是禁用的,您必須在項目的配置中激活它。原因是發布已啟用的功能會導致大多數程式碼庫發生重大更改。
什麼是下一個步驟?
空引用異常是 .NET 和大多數編程語言中非常常見的問題。幸運的是,我們都可以責怪托尼·霍爾。他發明了空引用,甚至稱其為十億美元的錯誤。
別開玩笑了,我們怎樣才能避免這樣的問題呢?一種替代方法是遵循我的黃金法則:如果它可以為空,那麼它將為空!
如今,幸運的是,在對抗 NullReferenceException 時,我們可以得到編譯器本身的幫助。在 C# 8.0 中啟用“可空引用類型”功能,這樣您就可以根據需要防止事物為空。這讓我們可以對我的舊規則進行有趣的旋轉:如果它不能為空,它就永遠不會為空。編譯器不允許!
您想了解更多關於 C#、異常和其他相關主題的信息嗎?如果是這樣,請與Stackify 博客保持一致,因為我們總是發布有關這些主題的帖子以及更多內容。
Stackify 前綴:程式碼探查器開發人員可以信任
在推送程式碼之前,您必須改善用戶體驗並優化瓶頸。為使這成為可能,請確保利用您可以使用的工具的強大功能。以 Stackify 工具為例。Stackify提供了一個名為Prefix的工具,它允許您監控用 .NET、Java、PHP、Node.js、Python 或 Ruby 編寫的 Web 應用程序。
Prefix 是一個非常輕量級的程式碼分析器,它甚至可以幫助最有經驗的開發人員發現緩慢的 SQL 查詢甚至隱藏的異常。使用 Prefix,開發人員可以在編寫程式碼時驗證其性能。結果,他們推送了更好的程式碼來測試並收到更少的支持票。
Stackify 最近推出了Prefix v4,目前仍處於測試階段。此版本是對 Stackify 久經考驗的分析工具的改進重建。
有了這個新的和改進的 Prefix,開發人員可以獲得更多操作系統支持、更多編程語言、現代 .NET 分析、專用日誌查看器,並且 Prefix 現在是適用於 Windows 和 macOS 的本機應用程序。
不僅。當您運行應用程序時,Prefix 在後台發揮其魔力,提供所有 Web 請求的詳細快照。使用 Stackify Prefix,您將能夠跟踪應用程序的性能,還可以發現隱藏的異常、慢查詢和其他問題。立即下載前綴。