[英]Dereference of a possibly null reference ... Can my code be simplified?
我的項目是 C# 中的.Net-6 Blazor WebAssembly(托管)。 可以簡化我的代碼以避免可空警告嗎? 我希望該人的客戶 ID 在來自 ApplicationUser 對象的身份名稱(變量是“_Name”)的頁面變量中。 謝謝。
List<Person> listPersons = (List<Person>)(await PService.GetPersons()).ToList();
Person oPerson = new Person();
if (listPersons != null){
oPerson = (Person)listPersons.Where(p => p.Name!.Equals(_Name)).FirstOrDefault();
}
if (oPerson != null) {
_UID_CUSTOMER = oPerson.UID_CUSTOMER;
}
當您使用可空引用類型功能時,您需要考慮,對於每個(引用)變量,該變量是否允許 null。
這與值類型沒有什么不同,例如int
。 你不會做
int a = 5;
if (a != null) { // ... }
因為a
永遠不可能是 null。 你需要使用int?
數據類型甚至允許a
null。
當然,有辦法打破 Nullable Reference Type 功能 - 例如忽略警告。
讓我們使用您的代碼並解決一些問題。 我將添加行號。
1 List<Person> listPersons = (List<Person>)(await PService.GetPersons()).ToList();
2 Person oPerson = new Person();
3 if (listPersons != null){
4 oPerson = (Person)listPersons.Where(p => p.Name!.Equals(_Name)).FirstOrDefault();
5 }
6 if (oPerson != null) {
7 _UID_CUSTOMER = oPerson.UID_CUSTOMER;
8 }
await PService.GetPersons()
返回一個IEnumerable<Person>
。 因為沒有?
,這意味着整個 object 不能是 null。 此外,每個元素(流中的每個 Person object)不能是 null。 如果您真的希望PService.GetPersons()
為您提供數據或null,則返回類型將為Task<IEnumerable<Person>?>
。
將IEnumerable<Person>
轉換為List<Person>
是危險的。 你得到一個IEnumerable<Person>
,一個接口。 底層集合可以是一個列表,也可以是一個數組,或者其他實現IEnumerable
的東西。 當PService.GetPersons()
的實現發生變化時,將其轉換為 List 可能會導致運行時錯誤。
在轉換為列表之后運行ToList()
沒有多大意義。 已經是清單了。 實際上,假設您沒有遇到強制轉換異常,如果 List 為 null,此方法將通過異常。 這完全消除了進行 null 檢查的意義。
所以,這是一個更好的第 1 行:
IEnumerable<Person> people = await PSService.GetPersons();
IEnumerable<Person>
,如果您只打算使用一次 stream ,則無需轉換為 List 。您將oPerson
的默認值設置為 Person 的新實例,並且數據類型 ( Person
) 表示它永遠不能保存 null 值。 但是,在第 4 行,您使用FirstOrDefault
,“默認”將為 null。 所以我們需要改變數據類型來解決這個問題。
此外,我們將重寫第 4 行,使第 4 行始終運行,並且不需要在第 2 行初始化變量。
事實上,這整行是不需要的,因為它只是變量名。 所以刪除它。
檢查listPersons
(現在稱為people
)的可空性沒有意義,因為您已經告訴編譯器它不能是 null。 刪除這些行。
在 Where you have Name..Equals()
中。 !
是“零寬恕”運算符。 問題在於,如果Name
是 null ,那么.Equals()
將引發異常。 將.Equals
替換為==
。 (這都是假設Name
的數據類型是string?
)。
最后的演員陣容也是不必要的。 FirstOrDefault
將返回一個Person
(或 null),因此將其轉換為相同的數據類型是浪費的。
Person? oPerson = people.FirstOrDefault(p => p.Name == _Name);
旁注,我不同意將FirstOrDefault
中的“默認”值設為 Person 的新實例。 我的觀點是FirstOrDefault
的默認值應該是 null。 對我來說,這對您的代碼具有語義意義。 您正在查看列表以查找匹配的人。 如果你找不到一個,那么你會得到 null,而不是一些新的空人。
這些都很好。
但是,如果_UID_CUSTOMER
的值在執行這些行之前已經是 null,則可以簡化這些行。 在這種情況下,所有行都可以替換為:
_UID_CUSTOMER = oPerson?.UID_CUSTOMER;
這表示:
同樣,僅當您在執行此行之前不關心_UID_CUSTOMER
的值時,這才有效。 如果只想在oPerson
不是 null 時覆蓋_UID_CUSTOMER
,請將其改回 if 語句。
所以,把它們放在一起,你會得到
IEnumerable<Person> people = await PSService.GetPersons();
Person? oPerson = people.FirstOrDefault(p => p.Name == _Name);
_UID_CUSTOMER = oPerson?.UID_CUSTOMER;
您可以通過從 csproj 文件中刪除此設置來避免可空警告
<Nullable>enable</Nullable>
並有這些設置
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.