Apparentemente Nullable<int>e int?hanno un valore equivalente. Ci sono motivi per sceglierne uno rispetto all'altro?
Nullable<int> a = null;
int? b = null;
a == b; // this is true
Apparentemente Nullable<int>e int?hanno un valore equivalente. Ci sono motivi per sceglierne uno rispetto all'altro?
Nullable<int> a = null;
int? b = null;
a == b; // this is true
Risposte:
Nessuna differenza.
int?è solo una scorciatoia per Nullable<int>, che a sua volta è l'abbreviazione di Nullable<Int32>.
Il codice compilato sarà esattamente lo stesso di quello che scegli di utilizzare.
Il ?modulo è solo una scorciatoia per il tipo completo. La preferenza personale è l'unico motivo per scegliere l'uno sull'altro.
Dettagli completi qui .
La sintassi
T?è una scorciatoia perNullable<T>, doveTè un tipo di valore. Le due forme sono intercambiabili.
Mentre Sono completamente d'accordo che nella maggior parte dei casi sono gli stessi, di recente ho sono imbattuto in una situazione, quando v'è una differenza tra i due. Per i dettagli cruenti vedi questa domanda , ma per darti un rapido esempio qui:
void Test<T>(T a, bool b)
{
var test = a is int? & b; // does not compile
var test2 = a is Nullable<int> & b; // does compile
}
La prima riga fornisce i seguenti messaggi di errore:
error CS1003: Syntax error, ':' expected
error CS1525: Invalid expression term ';'
Se sei curioso di sapere il motivo esatto di questo, ti consiglio vivamente di controllare la domanda già collegata , ma il problema di base è che nella fase di parsing dopo un is(o un as) operatore, quando affrontiamo un ?token controlliamo se il successivo token può essere interpretato come un operatore unario ( &potrebbe essere uno) e in tal caso: al parser non interessa la possibilità che il ?token sia un modificatore di tipo, usa semplicemente il tipo prima di esso e analizzerà il resto come se ?token erano un operatore ternario (quindi l'analisi fallirà).
Quindi, sebbene in generale int?e Nullable<int>siano intercambiabili, ci sono alcuni casi d'angolo in cui producono risultati completamente diversi, a causa di come il parser vede il tuo codice.
testè fissato con una parentesi, quindi var test = (a is int?) & b;. Può anche essere fissato con var test = a is int? && b;, e dato che bè un parametro di valore semplice (senza effetti collaterali sulla valutazione) sembra strano preferire &sopra &&.
?è un carattere chiave.
int?come un'operazione ternaria ( var test = a is int? <return if true> : <return if false>), non un int nullable.
boolsovraccarichi. Questi sono operatori logici booleani (il &for bool) e operatori logici condizionali booleani (il &&for bool). Notare come la prima di queste sottosezioni sia chiaramente denominata logica . Ricorda, in C # non ci sono conversioni ("cast") tra booli tipi numerici e!
Apparentemente c'è una differenza tra i due quando si utilizza la generazione di Entity Framework (EF) code-first:
Quando la tua entità contiene una proprietà dichiarata come:
public class MyEntity
{
public Nullable<int> MyNullableInt { get; set; }
}
EF non genererà una proprietà nullable e dovrai forzare il generatore a renderlo nullable in questo modo:
public class YourContext : DbContext
{
public DbSet<MyEntity> MyEntities{ get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<MyEntity>().Property(x => x.MyNullableInt).IsOptional();
}
}
D'altra parte, se dichiari la tua entità come:
public class MyEntity
{
public int? MyNullableInt { get; set; }
}
il generatore EF genererà una proprietà nullable con un campo nullable nella tabella di database corrispondente.
Nullabledefinizione da qualche parte, perché con il built-in Nullable<T>, non è possibile per EF vedere la differenza tra i due. Anche se i ragazzi di EF volessero trattarli in modo diverso, non potrebbero.
Nullable è un tipo generico, ma int? non è.
Ci sono alcuni scenari in cui Nullable dovrebbe essere usato su int?
per esempio: qui non puoi sostituire Nullable con int?
come puoi cambiare il codice sottostante senza usare Nullable ?
class LazyValue<T> where T : struct
{
private Nullable<T> val;
private Func<T> getValue;
// Constructor.
public LazyValue(Func<T> func)
{
val = null;
getValue = func;
}
public T Value
{
get
{
if (val == null)
// Execute the delegate.
val = getValue();
return (T)val;
}
}
}
Nullable<T>èNullable<int>