2011-09-14 15 views
15

Nel tentativo di utilizzare il seguente codice:Perché non posso dichiarare un elenco generico come annullabile?

private Nullable<List<IpAddressRange>> ipAddressRangeToBind; 

Ma io sono sempre il seguente avviso:

L'elenco tipo deve essere un tipo di valore non annullabile in per usarlo come un parametro 'T' nel tipo o metodo generico 'System.Nullable'.

risposta

35

List<T> è già un tipo di riferimento (per ogni tipo di T) - è possibile dichiarare solo Nullable<T> dove T è un tipo di valore non annullabile (è dichiarato come Nullable<T> where T : struct).

Ma va bene così, perché se si dichiara:

private List<IpAddressRange> ipAddressRangeToBind; 

allora si può ancora avere

ipAddressRangeToBind = null; 

perché i tipi di riferimento sono sempre annullabile.

+0

che risposta !!!, grazie ..... per spiegare facilmente – Ajay2707

9

List<IpAddressRange> è un tipo di riferimento - è già annullabile - infatti verrà inizializzato a null da tale dichiarazione.

5

si può semplicemente usare così com'è:

List<IpAddressRange> ipAddressRangeToBind = null; 

List è già annullabile.

+0

vero vero, perché non posso farlo anche se per interesse ...? – Exitos

+2

Immagino perché, come ha spiegato Jon Skeet, il vincolo 'Nullable dove T: struct' e' IpAddressRange' non è una 'struct'. Perché il vincolo che chiedi?Questa è una domanda diversa :) –

+0

@ Pete2k: ho aggiunto una risposta sul motivo per cui non esiste il vincolo. Non è stata la prima risposta, quindi non voglio reclamare il merito della risposta, ma è stato troppo lungo per inserire un commento ... –

4

I tipi di riferimento non possono essere raggruppati in Nullable<T> a causa di un vincolo where T : struct sul generico.

Le ragioni di questo vincolo sono:

  1. tipi di riferimento sono già annullabile per definizione, e
  2. Nullable non è molto efficiente dello spazio, ma più di un supporto di valori Null "logico".

Nullable<T> ha una proprietà bool HasValue e un tipo T struttura Value che contiene il valore effettivo value-type.

Anche se HasValue == false (ovvero se la variabile con valore nulla spostato è impostata su null), ANCORA si utilizza lo spazio per il tipo di valore come se fosse lì.

E 'logicamente annullabile per consentire di specificare opzionale comportamento, ma non salva qualsiasi spazio. Questo è molto simile a come boost :: opzionale funziona in C++.

+0

Ora vedo cosa è la clausola Where! – Exitos

+0

Un sacco di fastidi con 'Nullable ' deriva dal desiderio di far finta che un'istanza vuota sia 'null'. Una decisione sfortunata, IMHO, dal momento che impedisce metodi come 'TryGetValue', che possono o meno restituire un' T', semplicemente restituendo un 'TValue?' Senza doversi preoccupare del tipo di 'TValue' (se il 'HasValue' dell'elemento restituito è falso, la chiave non esiste, se' HasValue' è true, la chiave esiste anche se il 'Valore' memorizzato risulta essere' null'). D'altra parte, mentre i tipi nullable dovrebbero logicamente essere covarianti con il loro parametro di tipo ... – supercat

+0

... (poiché ogni 'Animale?' Dovrebbe essere in grado di contenere il contenuto di qualsiasi 'Cat?'), Facendo funzionare la covarianza mentre si ha un cast di 'Animal?' o 'Animal ??' to' Object' conserva il grado di nullability, richiederebbe che la conversione da un tipo nullable a 'Object' non utilizzi il normale boxe. Secondo le normali regole di boxe, i tipi di valore in box sono * sempre * mutabili (anche se il tipo di valore sottostante è presumibilmente "immutabile"). Peccato, dal momento che un tale design aumenta la difficoltà di fare cose come un'interfaccia covariante "dizionario leggibile" per quanto riguarda i tipi di valori memorizzati in esso. – supercat

Problemi correlati