簡體   English   中英

C# 9 可空類型問題

[英]C# 9 Nullable types issues

考慮以下(VS 16.8.0 Preview 2.1 C# 9.0 preview)代碼:

#nullable enable

using System.Collections.Generic;

class Archive<T> where T : notnull 
{
  readonly Dictionary<string, T> Dict = new();

  public T? GetAt(string key) 
  { 
    return Dict.TryGetValue(key, out var value) ? value : default;
  }
}

class Manager 
{
  public int Age { get; set; }
}

class Main34 
{
  long F3() 
  {
    Archive<long> a = new();
    var johnAge = a.GetAt("john");
    if (johnAge is null) return -1; // Error CS0037  Cannot convert null to 'long' because it is a non - nullable value type
    return johnAge; 
  }

  long F4() 
  {
    Archive<Manager> a = new();
    var johnAge = a.GetAt("john");
    //if (johnAge is null) return -1;
    return johnAge.Age; // Correct ! warning "Derefrencing of a possibly null reference" will be removed if line above unremarked 
  }
}

我很難理解/解決 F3 中的錯誤,似乎編譯器認為 johnAge 存在long long? (正如我通過在 VS 中懸停在它上面來驗證的那樣)盡管Archive<T>.GetAt的返回是T?

有沒有辦法讓通用存檔可以做我想做的事情(即使 T 是不可為空的基本類型,即 long,也返回 Nullable 的 GetAt 方法)?

從根本上說,這歸結為可空值類型和可空引用類型非常非常不同。 CLR 知道可空值類型,但就 CLR 而言,可空引用類型只是“普通的引用類型,有一個屬性告訴編譯器是否應將其視為可為空的”。

T具有notnull約束時,類型T? 只在 IL 中編譯為T 它必須 - 它不能編譯為Nullable<T> ,因為Nullable<T>T約束為值類型。

因此,對於Archive<long> ,如果在字典中找不到鍵,則GetAt方法將返回 0L - 它不會(也不能)返回Nullable<long>的空值,這就是您的F3代碼有效地期待。

整個“可空引用類型”功能的缺點是試圖在基本上沒有它的類型系統上添加可空感知的“貼面”。 我敢肯定,如果現在從頭開始設計新的運行時和語言,它會嘗試更緊密地統一這一點。 事實上,我相信這個特性仍然有很多價值——但是當涉及到泛型時,它肯定會讓事情變得非常棘手。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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