Un tipo di riferimento non annullabile in C # 8 può essere nullo in fase di esecuzione?


10

Mi sembra che non ci sia davvero alcuna garanzia che una variabile non nullable non avrà mai null. Immagina di avere una classe che ha una proprietà che non è nullable:

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

Ora potrebbe sembrare che ora non può essere nullo. Ma se facciamo riferimento a questa classe con un'altra libreria che non utilizza un contesto nullable, nulla impedisce che invii null all'interno.

È corretto o ci sono anche alcuni controlli di runtime che forse lo garantiscono?


È public void Foo(string test){...}o public Foo(string test){...}?
huMpty duMpty

Grazie, l'ho risolto. Questo è ciò che accade quando l'uomo si affida troppo a R # per generare costruttori :)
Ilya Chernomordik,

2
C # 9 aggiungerà (probabilmente) una validazione nulla semplificata .
Steven,

In breve, la funzione "tipi di riferimento annullabili" è completamente interrotta.
Alejandro,

Risposte:


9

Questo è ciò che dice MS su ( https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/upgrade-to-nullable-references#interfaces-with-external-code ):

Il compilatore non può convalidare tutte le chiamate alle API pubbliche, anche se il codice è compilato con contesti di annotazione nullable abilitati. Inoltre, le tue librerie potrebbero essere utilizzate da progetti che non hanno ancora optato per l'utilizzo di tipi di riferimento nullable. Convalida input per API pubbliche anche se li hai dichiarati come tipi non annullabili.


2

qualcuno può sempre fare

var myFoo = new Foo(null);

Forse puoi usare 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;}
}

sì, hai ragione, è solo un avvertimento, comunque. Spero che in futuro possano davvero farcela in qualche modo, come ad esempio Kotlin
Ilya Chernomordik,

2

Hai ragione, un altro codice che non utilizza la nuova funzionalità potrebbe assegnare null a questa proprietà, non ci sono verifiche di runtime, è solo un suggerimento del complier.

Puoi sempre farlo da solo se vuoi un controllo di runtime:

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

Nota che puoi garantire di non essere nullo nella maggior parte del tuo codice, devi solo aggiungere protezioni all'API pubblica di livello superiore e assicurarti che le classi siano adeguatamente sigillate ecc.

Ovviamente le persone possono ancora usare la riflessione per correggere il codice, ma poi è su di loro


Quindi questo significa che posso ancora ottenere un'eccezione di riferimento null anche se utilizzo un tipo non annullabile, giusto?
Ilya Chernomordik,

Bene .... non puoi nel codice che compili, perché hai i suggerimenti su ... ma il codice di altre persone che non ha i suggerimenti su, ma fai riferimento al tuo codice - sì, possono ottenere un'eccezione nulla
Milney il

Bene, se ad esempio un automapper usa il tuo costruttore, o qualcosa del genere, sei ancora tu a ricevere l'eccezione :)
Ilya Chernomordik,

Of course people can still use reflection to f*** your code up, vero, vero davvero. Puoi sicuramente usare la riflessione per fare questo, è raccomandato , no , lo fanno ancora le persone, sì.
Çöđěxěà il

2

Anche nel tuo codice, se decidi di farlo, puoi passare nullusando l'operatore che perdona nulla. null!è considerato non nullo per quanto riguarda l'analisi di nullità del compilatore.


-1

Per gestire i controlli null e anche rendere leggibile il codice, suggerisco il modello Null Object Design.

Più lettura qui:

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

Fondamentalmente, comporta la creazione di un nuovo oggetto derivato dalla stessa interfaccia e con istanza nulla.

Esempio:

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()  
    { }  
}  

I valori null non possono essere evitati, tuttavia possono essere controllati in modo pulito.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.