Bisakah tipe referensi yang tidak dapat dibatalkan dalam C # 8 menjadi null dalam runtime?

10

Sepertinya saya benar-benar tidak ada jaminan bahwa variabel yang tidak dapat dibatalkan tidak akan pernah memiliki nol. Bayangkan saya memiliki kelas yang memiliki satu properti yang tidak dapat dibatalkan:

public class Foo
{
    public Foo(string test)
    {
        Test = test;
    }
    public string Test {get;set;}
}

Sekarang yang mungkin tampak seperti sekarang tidak boleh nol. Tetapi jika kita mereferensikan kelas ini dengan pustaka lain yang tidak menggunakan konteks nullable, tidak ada yang menghentikan pengiriman nol di sana.

Apakah itu benar atau ada beberapa pemeriksaan runtime juga yang mungkin memastikan ini?

Ilya Chernomordik
sumber
Apakah itu public void Foo(string test){...}atau public Foo(string test){...}?
huMpty duMpty
Terima kasih, saya sudah memperbaikinya. Itulah yang terjadi ketika manusia terlalu bergantung pada R # untuk menghasilkan konstruktor :)
Ilya Chernomordik
2
C # 9 akan (kemungkinan) menambahkan validasi nol yang disederhanakan .
Steven
Singkatnya, fitur "tipe referensi yang dapat dibatalkan" benar-benar rusak.
Alejandro

Jawaban:

9

Inilah yang dikatakan MS tentang ( https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/upgrade-to-nullable-references#interfaces-with-external-code ):

Kompiler tidak dapat memvalidasi semua panggilan ke API publik Anda, bahkan jika kode Anda dikompilasi dengan konteks anotasi nullable diaktifkan. Selanjutnya, perpustakaan Anda dapat dikonsumsi oleh proyek yang belum memilih menggunakan jenis referensi yang dapat dibatalkan. Validasi input ke API publik meskipun Anda telah menyatakannya sebagai tipe yang tidak dapat dibatalkan.

Dmitri Tsoy
sumber
2

seseorang selalu bisa melakukannya

var myFoo = new Foo(null);

Mungkin Anda bisa menggunakan Domain Driven Design

public class Foo
{
    public Foo(string test)
    {
         if (string.IsNullOrWhiteSpace(test))
             throw new ArgumentNullException(nameof(test));

         Test = test;
    }
    public string Test {get;private set;}
}
huMpty duMpty
sumber
ya, Anda benar, itu hanya peringatan saja saya kira. Saya berharap di masa depan mereka dapat benar-benar menegakkannya seperti di misalnya Kotlin
Ilya Chernomordik
2

Anda benar, kode lain yang tidak menggunakan fitur baru dapat menetapkan null untuk properti ini, tidak ada pemeriksaan run-time, itu hanya petunjuk pengubah.

Anda selalu bisa melakukannya sendiri jika Anda ingin pemeriksaan runtime:

public string Test { get; set{ if (value == null) throw new ArgumentNullException() } }

Perhatikan bahwa Anda dapat menjamin tidak ada null di sebagian besar kode Anda, Anda hanya perlu menambahkan penjaga ke API Publik tingkat atas Anda dan memastikan kelas disegel dengan tepat, dll.

Tentu saja orang masih dapat menggunakan refleksi untuk memperbaiki kode Anda, tetapi kemudian pada mereka

Milney
sumber
Jadi ini secara efektif berarti saya masih bisa mendapatkan Null Reference Exception meskipun saya menggunakan tipe yang tidak dapat dibatalkan, kan?
Ilya Chernomordik
Baiklah .... Anda tidak dapat memasukkan kode yang Anda kompilasi, karena Anda memiliki petunjuk tentang ... tetapi kode orang lain yang tidak memiliki petunjuk tersebut, tetapi referensi kode Anda - ya mereka bisa mendapatkan pengecualian nol
Milney
Nah, jika misalnya automapper menggunakan konstruktor Anda, atau sesuatu seperti itu, tetap Anda yang akan mendapatkan pengecualian :)
Ilya Chernomordik
Of course people can still use reflection to f*** your code up, benar, benar memang. Anda pasti dapat menggunakan refleksi untuk melakukan ini, apakah itu disarankan , tidak , apakah orang masih melakukannya, ya.
Çöđěxěŕ
2

Bahkan dalam kode Anda sendiri, jika Anda memilih untuk melakukannya, Anda dapat lulus null, menggunakan operator null-forgiving. null!dianggap tidak-nol sejauh analisis nullability kompiler yang bersangkutan.

Damien_The_Unbeliever
sumber
-1

Untuk menangani cek nol dan juga membuat kode Anda dapat dibaca, saya sarankan pola Desain Obyek Null.

Lebih banyak membaca di sini:

https://www.c-sharpcorner.com/article/null-object-design-pattern/

Pada dasarnya, ini melibatkan pembuatan objek baru yang berasal dari antarmuka yang sama dan memiliki instance nol.

Contoh:

public class NullExample : IExample  
{  
    private static NullExample _instance;  
    private NullExample()  
    { }  

    public static NullExample Instance  
    {  
        get {  
            if (_instance == null)  
                return new NullExample();  
            return _instance;  
        }  
    }  

    //do nothing methods  
    public void MethodImplementedByInterface1()  
    { }  

    public void MethodImplementedByInterface1()  
    { }  
}  

Nulls tidak dapat dihindari, tetapi mereka dapat diperiksa dengan bersih.

Gauravsa
sumber