2009-10-01 13 views
9

Ho giocato con i contratti di codice su VS2008 (http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx).
Sono sicuramente gentili e forniscono una valida alternativa ai controlli if-then-throw nei metodi.Contratti di codice in .NET 4.0, nessuna gioia per i fan dei tipi di riferimento non annullabili?

Tuttavia spero che possano soddisfare il bisogno che sento fortemente per i tipi di riferimento non annullabili.
Purtroppo, da quello che ho potuto vedere questo non sembra essere il caso.
Questo è quello che ho capito:

  • Qualcosa di simile sarà ancora causare problemi in fase di esecuzione:
    MyClass a = null;
    a.ToString();

  • devo ancora scrivere in modo esplicito controlli, anche se in modo più conciso e snello .

  • A meno che non si usi VS Team System, è possibile utilizzare solo i contratti di codice per controllare le cose in fase di esecuzione, senza vantaggi in fase di compilazione.
    Significa che devi ancora gestire le cose quando qualcosa va storto.
    Non molto diverso dalla gestione di una semplice eccezione.

  • Anche con l'analisi statica VSTS non è buono come quello eseguito in fase di esecuzione.
    Questo è perfettamente comprensibile, tuttavia è un altro segno che questa funzione è pensata per l'utilizzo in runtime.

favore correggetemi se sbaglio, ma da quello che vedo non c'è modo Code Contracts può rendere la vita più facile, e miei programmi più robusto, come i tipi di riferimento non annullabili avrebbe fatto.

Non fraintendetemi, non mi piacciono i contratti di codice.
Sono un ottimo miglioramento dell'intero framework.
È solo che se questo non colma il vuoto che C# lascia non avendo tipi di riferimento non annullabili, a questo punto temo che non lo farà nulla.
Cosa ne pensi?

+0

Bene ... c'è ora (2017) un prototipo per giocare con il tipo di riferimento * Nullable *. Vedere [la mia risposta sotto] (https://stackoverflow.com/a/47339130/6309) – VonC

risposta

20

Penso che tu abbia ragione su questo. Il controllo di riferimento non annullabile al momento della compilazione era la caratteristica killer che stavo aspettando nei Contratti di codice, e non è davvero lì.

Per chi si chiede cosa significhi, si consideri un'analogia con i tipi di valore.Non erano annullabili in origine, ma ora sono se si mette un punto interrogativo dopo il nome del tipo:

int? n; 

Per ragioni di coerenza sarebbe ideale se lo stesso valeva per i tipi di riferimento. Ma ciò interromperà tutti i programmi C# esistenti e quindi non è un'opzione. Nel linguaggio di ricerca Spec# sono andati con l'utilizzo di un suffisso punto esclamativo a significare non annullabile:

string! s = "Hello"; 

Come per i tipi di valore ordinario, il compilatore controlla staticamente che una variabile string! non è utilizzato su qualsiasi percorso di codice prima che abbia stato inizializzato (credo che SpeC# richiede che la dichiarazione e l'inizializzazione avvengano nella stessa dichiarazione).

Inoltre, vieta l'assegnazione di null a tale variabile.

E, naturalmente, vieta l'assegnazione di un numero ordinario string a string!. Quindi, come fare a colmare il divario tra i due tipi di tipo? Scrivendo un assegno:

string x = GetStringFromSomewhere(); 

if (x != null) 
    s = x; // okay because compiler sees null check 

La triste verità è che la maggior parte delle variabili di riferimento nella maggior parte dei programmi sono suscettibili di essere non annullabile se il programma è corretto. Le variabili nulle sono in minoranza. Eppure sono predefiniti.

Another bad idea from the 1960s!

+1

Cosa sarebbe 'default (stringa!)' Essere? Quale sarebbe il valore di un campo 'stringa!' In una struttura che ho inizializzato con il costruttore predefinito? – configurator

+1

Questi casi semplicemente non dovrebbero essere compilati - 'default (stringa!)' È una contraddizione: "Qual è il valore di pre-inizializzazione della cosa che deve essere inizializzato prima che il suo valore possa essere letto?" E forse nemmeno i campi non annullabili possono essere ammessi nelle strutture. Le strutture sono già schifose. –

+1

Un fatto irritante è che il CLR ha un modo oscuro per consentire la creazione di oggetti di una classe senza eseguire * qualsiasi * costruttore - ma se lo si utilizza, tutte le scommesse sono disattivate. Ciò significherebbe che in alcune circostanze patologiche il valore di un 'T!' Potrebbe essere 'null'. –

3

Non sono sicuro di quale problema venga risolto da "tipi di riferimento non annullabili". Ok quindi questo codice è molto meno probabile di un'eccezione: -

a.ToString(); 

Tuttavia è più probabile che sia corretta perché una è non annullabile? Quale sarebbe il valore iniziale di a? Probabilmente alcune istanze "vuote" di default del tipo. In tal caso non è più probabile che le cose siano più difficili da eseguire il debug poiché i valori a cui dovrebbe essere assegnato un valore non lo sono. Solo avere un comportamento predefinito piuttosto che causare un'eccezione non sembra una cosa che vorrei.

+0

Vedo il vostro punto ma non mi dispiacerebbe affatto dover fornire un riferimento o creare un'istanza di una classe quando si dichiara una variabile. – RobSullivan

+1

Eppure in molti casi non si sarebbe in grado di fornire la variabile con un riferimento __correct__ al punto di dichiarazione, quindi si dovrebbe dargli una temporanea. Quindi sei di nuovo al punto di partenza. Si noti inoltre che non nullable richiederebbe verifiche di runtime su ogni assegnazione alla variabile per vedere se ciò che viene assegnato è nullo. – AnthonyWJones

+1

Spero davvero che nessuno dichiari tutte le variabili con un valore solo per "evitare riferimenti null". Ci dovrebbe essere un motivo per creare una variabile e assegnare un valore. Se non sei nella posizione di fornire un valore corretto, allora l'API/codice è abbastanza rotto. – MichaelGG

-2

piuttosto che usare nulla è possibile utilizzare un valore predefinito come String.Empty non v'è alcuna necessità di valori nulli

3

Credo che il concetto di un tipo di riferimento non annullabile sarebbe davvero utile per le proprietà ORM generato che mappano alla banca dati campi. Spesso non è possibile distinguere dalla proprietà (in genere digitare string) se il campo sottostante è annullabile o meno. Con i tipi di valori nullable puoi, semplicemente cercando il punto interrogativo.

Non sono troppo preoccupato per il controllo statico, a parte l'ovvio pippo! = null; in mancanza, ma l'intellisense sarebbe molto utile come suggerimento per l'intento variabile, credo.

0

Il controllo di riferimento non annullabile in fase di compilazione era la caratteristica killer che stavo aspettando in Contratti di codice, e non è proprio lì.

Aggiornamento 2017 (8 anni dopo), mentre il tipo di riferimento non annullabile non è ancora presente ... potrebbe essere possibile il tipo di riferimento nullable.

Mads Torgersen (linguaggio C# di Microsoft PM) non menzionarlo in this tweet:

Il prototipo di tipi di riferimento nullable è finalmente arrivato!

Questo è dettagliato in "Introducing Nullable Reference Types in C#" e in questo video "new features available C# 7.1 and 7.2".

Ciò può essere ottenuto se aggiungiamo solo un nuovo tipo di "sicuro" tipo di riferimento e quindi reinterpretiamo i tipi di riferimento esistenti come l'altro tipo "sicuro".Più in particolare, pensiamo che il significato di default di tipi di riferimento non annotate come la stringa dovrebbe essere tipi di riferimento non annullabili, per un paio di motivi:

Noi crediamo che sia più comune a voler un riferimento non essere nullo I tipi di riferimento Nullable sarebbero il tipo più raro (anche se non abbiamo dati validi da indicarci per quanto), quindi sono quelli che dovrebbero richiedere una nuova annotazione. La lingua ha già una nozione di - e una sintassi per - tipi di valori nullable. L'analogia tra i due renderebbe l'aggiunta del linguaggio concettualmente più semplice e linguisticamente più semplice.
Sembra giusto non dover gravare te stesso o il tuo consumatore con valori nulli ingombranti a meno che tu non abbia deciso attivamente di volerlo. I nulli, non l'assenza di essi, dovrebbero essere la cosa a cui devi esplicitamente optare.
Ecco come si presenta:

class Person 
{ 
    public string FirstName; // Not null 
    public string? MiddleName; // May be null 
    public string LastName; // Not null 
} 

Questa classe è ora in grado di esprimere l'intento che ognuno di noi ha un primo e un cognome, ma solo alcune persone hanno un secondo nome.

Così arriviamo alla ragione per cui chiamiamo questa funzione linguistica "tipi di riferimento nullable": quelli che vengono aggiunti alla lingua. Quelli non ingenui sono già lì, almeno sintatticamente.

questo è ancora un prototipo , e potrebbe finire (o meno) nella lingua.
Ulteriori informazioni su "The C# Nullable Reference Types Preview".

Problemi correlati