C # 9 Masalah tipe Nullable
Pertimbangkan kode berikut (VS 16.8.0 Preview 2.1 C # 9.0):
#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
}
}
Saya mengalami kesulitan pemahaman / mengatasi kesalahan dalam F3, Sepertinya compiler berpikir johnAge ada longtidak long?(seperti yang saya diverifikasi oleh melayang di atas dalam VS) meskipun kembalinya Archive<T>.GetAtmakhlukT?
Apakah ada cara untuk memiliki Arsip generik yang akan melakukan apa yang saya inginkan (metode GetAt yang mengembalikan Nullable bahkan ketika T adalah tipe dasar non nullable yaitu long)?
Jawaban
Pada dasarnya, ini bermuara pada tipe nilai nullable dan tipe referensi nullable menjadi sangat, sangat berbeda. CLR mengetahui jenis nilai nullable, tetapi sejauh menyangkut CLR, jenis referensi nullable hanyalah "jenis referensi normal, dengan atribut yang memberi tahu compiler apakah ia harus dianggap nullable atau tidak".
Ketika Tmemiliki notnullbatasan, tipe T?hanya dikompilasi ke Tdalam IL. Itu harus - tidak dapat dikompilasi Nullable<T>, karena Nullable<T>batasan Tmenjadi tipe nilai.
Jadi untuk sebuah Archive<long>, GetAtmetode akan mengembalikan 0L jika kunci tidak ditemukan dalam kamus - itu tidak akan (dan tidak bisa) mengembalikan nilai null dari a Nullable<long>, yang diharapkan kode Anda F3secara efektif.
Seluruh fitur "jenis referensi nullable" mengalami upaya untuk menambahkan "lapisan" kesadaran nullable melalui sistem jenis yang pada dasarnya tidak memilikinya. Saya yakin jika runtime dan bahasa baru sedang dirancang bersama dari awal sekarang, itu akan mencoba untuk menyatukan ini lebih dekat. Karena itu, saya yakin fitur tersebut masih memiliki banyak nilai - tetapi itu pasti membuat hal - hal menjadi sangat rumit dalam hal obat generik.