簡體   English   中英

取消引用可能的 null 參考...我的代碼可以簡化嗎?

[英]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  }

1號線

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 。

2號線

您將oPerson的默認值設置為 Person 的新實例,並且數據類型 ( Person ) 表示它永遠不能保存 null 值。 但是,在第 4 行,您使用FirstOrDefault ,“默認”將為 null。 所以我們需要改變數據類型來解決這個問題。

此外,我們將重寫第 4 行,使第 4 行始終運行,並且不需要在第 2 行初始化變量。

事實上,這整行是不需要的,因為它只是變量名。 所以刪除它。

3號線和5號線

檢查listPersons (現在稱為people )的可空性沒有意義,因為您已經告訴編譯器它不能是 null。 刪除這些行。

4號線

在 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,而不是一些新的空人。

第 6、7 和 8 行

這些都很好。

但是,如果_UID_CUSTOMER的值在執行這些行之前已經是 null,則可以簡化這些行。 在這種情況下,所有行都可以替換為:

_UID_CUSTOMER = oPerson?.UID_CUSTOMER;

這表示:

  • 如果oPerson是null,就用null
  • 如果 oPerson 不是 null,則使用 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM