Tipo di riferimento annullabile in C # 8 quando si utilizzano classi DTO con un ORM


9

Ho attivato questa funzione in un progetto con classi DTO (Data Transfer Object), come indicato di seguito:

public class Connection
    {
        public string ServiceUrl { get; set; }
        public string? UserName { get; set; }
        public string? Password { get; set; }
        //... others 
    }

Ma ottengo l'errore:

CS8618: La proprietà non annullabile "ServiceUrl" non è inizializzata. Valuta di dichiarare la proprietà come nullable.

Questa è una classe DTO, quindi non sto inizializzando le proprietà. Questa sarà la responsabilità del codice che inizializza la classe per garantire che le proprietà siano non nulle.

Ad esempio, il chiamante può fare:

var connection = new Connection
{
  ServiceUrl=some_value,
  //...
}

La mia domanda: come gestire tali errori nelle classi DTO quando il contesto di nullability di C # 8 è abilitato?


3
Quando si esegue l'inizializzazione della costruzione nel modo in cui viene visualizzata, viene eseguita la funzione di costruzione predefinita (l'inizializzazione di ServiceUrl sul valore predefinito (che, per le stringhe, è null)). Quindi, viene eseguita l'istruzione di inizializzazione. Se lo vuoi non annullabile, deve uscire da tutti i costruttori inizializzati
Flydog57

POCO non significa che non ha un costruttore o che le proprietà non sono inizializzate. Significa Plain Old C# Object. Solo un oggetto come un altro, senza ereditare da alcuna classe speciale. Sospetto che tu abbia una domanda diversa . Come creare DTO -Data Transfer Objects
Panagiotis Kanavos il

This should be the responsibility of the one initializing the class to ensure that the properties are non-nullla classe dovrebbe essere sempre in uno stato valido. Se nullnon è consentito, la proprietà non dovrebbe mai essere nulla. Forse, invece di una stringa di base, dovresti usare una classe specializzata per l'URL che può avere un valore di Noneo "Missing", come la classe Option in F #. C # 8 ti consente di scrivere tali classi e di controllarle con la corrispondenza dei modelli
Panagiotis Kanavos,

@Panagiotis Kanavos, La classe, nel mio caso, ha il vincolo di essere Costruttore senza parametri. Quindi devo usare Proprietà Initializer: public string ServiceUrl { get; set; } = default! ;. Spero che Roslyn possa avere in futuro un modo per gestire l'inizializzazione tardiva al di fuori dell'ambito di ctor. Stavo usando MayBe <T> (come la classe Option), ma sono passato a Tipo di riferimento nullable in c # 8 per il nuovo codice.
M.Hassan,

I NRT non sono Maybes, infatti, i Maybes sono ora ancora più importanti e più facili da usare. A condizione che, ovviamente, vengano creati utilizzando idiomi C # che li rendono facili da lavorare con la corrispondenza dei modelli
Panagiotis Kanavos,

Risposte:


9

La soluzione successiva è raccomandata da EF Core e EF6 vedi

1) Inizializzando null!con un operatore perdonatore

public string ServiceUrl { get; set; } = null! ;
//or
public string ServiceUrl { get; set; } = default! ;

2) Utilizzando il campo di supporto:

        private string _ServiceUrl;
        public string ServiceUrl
        {
            set => _ServiceUrl = value;
            get => _ServiceUrl
                   ?? throw new InvalidOperationException("Uninitialized property: " + nameof(ServiceUrl));
        }


La domanda diceva che non poteva usare l' !operatore.
Athanasios Kataras,

Non posso usare! con type, ma il link che ho citato mostra come inizializzare usando null !. È una soluzione alternativa. Ho modificato la domanda.
M.Hassan,

8

Se non è nullable, cosa può fare il compilatore quando l'oggetto viene inizializzato?

Il valore predefinito della stringa è null, quindi lo farai

  1. entrambi devono assegnare un valore predefinito di stringa nella dichiarazione

    public string ServiceUrl { get; set; } = String.Empty;

  2. Oppure inizializza il valore nel costruttore predefinito in modo da eliminare l'avviso

  3. Usa l' !operatore (che non puoi usare)

  4. Renderlo nullable come indicato da robbpriestley.


4
Oppure aggiungi un costruttore che accetta l'URL del servizio come stringa non annullabile, ovviamente.
Jon Skeet,

ServiceUrl'non può essere = String.Empty. Esistono altre Proprietà di tipo complesso che non possono essere nulle, quindi ho usato defaultcome: 'public MyClass MyProperty {get; impostato; } = impostazione predefinita! 'per interrompere l'avvertimento. Questa classe (e altre) è un costruttore senza parametri e recentemente è inizializzato al di fuori dell'ambito di ctor.
M.Hassan,

0

Un'altra cosa che potrebbe tornare utile in alcuni scenari:

[SuppressMessage("Compiler", "CS8618")]

Può essere utilizzato sopra il membro o l'intero tipo.


Un'altra cosa da considerare è l'aggiunta #nullable disablein cima al file per disabilitare il riferimento nullable per l'intero file.

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.