Apa itu Nullability Tidak Diketahui dalam C # 8?

12

Dalam C # 8.0 kita dapat memiliki jenis referensi yang dapat dibatalkan. Dokumen menyatakan bahwa ada 4 jenis nullability. 3 yang pertama cukup jelas tetapi saya gagal memahami titik "tidak diketahui". Dokumen mengatakan ini digunakan dengan obat generik tetapi ketika saya mencoba memanggil metode pada variabel tipe T yang tidak dibatasi dalam obat generik, ia hanya memperingatkan seolah-olah jenisnya dapat dibatalkan. Saya gagal melihat perbedaan antara tidak diketahui dan nullable. Mengapa tidak diketahui ada? Bagaimana itu memanifestasikan dirinya?

Stilgar
sumber

Jawaban:

12

Ambil metode generik berikut:

public static T Get<T>(T value)
{
    return value;
}

Jika kita menyebutnya seperti itu Get<string>(s), pengembaliannya tidak dapat dibatalkan, dan jika kita lakukan Get<string?>(s), itu tidak dapat dibatalkan.

Namun jika Anda memanggilnya dengan argumen umum seperti Get<T>(x)dan Ttidak terselesaikan, misalnya itu adalah argumen umum untuk kelas generik Anda seperti di bawah ini ...

class MyClass<T>
{
    void Method(T x)
    {
        var result = Get<T>(x);
        // is result nullable or non-nullable? It depends on T
    }
}

Di sini kompiler tidak tahu apakah pada akhirnya akan dipanggil dengan tipe nullable atau non-nullable.

Ada batasan tipe baru yang bisa kita gunakan untuk memberi sinyal yang Ttidak boleh nol:

public static T Get<T>(T value) where T: notnull
{
    return value;
}

Namun, di mana Ttidak dibatasi dan masih terbuka, nullability tidak diketahui.

Jika tidak diketahui ini diperlakukan sebagai nullable maka Anda dapat menulis kode berikut:

class MyClass<T>
{
    void Method(T x)
    {
        var result = Get<T>(x);
        // reassign result to null, cause we we could if unknown was treated as nullable
        result = null;
    }
}

Dalam kasus Tyang tidak dapat dibatalkan, kita seharusnya mendapat peringatan. Jadi dengan jenis nullability yang tidak diketahui, kami ingin peringatan saat dereferencing, tetapi juga peringatan untuk penetapan yang berpotensi null.

Stuart
sumber
Ketika saya melakukan var result = Test.Get <T> (x); result.ToString (); kompiler mengeluh tentang dereferensi nilai yang mungkin nol. Saya tidak melihat bagaimana tidak diketahui bedanya dengan nullable dalam kasus ini.
Stilgar
1
Dalam hal peringatan, mereka berperilaku sama, tetapi secara semantik berbeda. Anda bisa mengatakan perbedaannya bersifat akademis, dan jika itu yang Anda maksud maka saya setuju.
Stuart
1
Saya masih ingin tahu mengapa perbedaan itu diperkenalkan. Tampaknya aneh untuk memperkenalkan perbedaan dalam bahasa untuk tujuan akademik.
Stilgar
Yang buruk, baca ulang spec, perbarui jawabannya, bagian terakhir menjelaskannya.
Stuart
1
Ah itu lebih seperti itu
Stilgar