Aparentemente Nullable<int>e int?são equivalentes em valor. Existe alguma razão para escolher um em vez do outro?
Nullable<int> a = null;
int? b = null;
a == b; // this is true
Aparentemente Nullable<int>e int?são equivalentes em valor. Existe alguma razão para escolher um em vez do outro?
Nullable<int> a = null;
int? b = null;
a == b; // this is true
Respostas:
O ?formulário é apenas uma abreviação para o tipo completo. A preferência pessoal é a única razão para escolher um em vez do outro.
Detalhes completos aqui .
A sintaxe
T?é um atalho paraNullable<T>, ondeTé um tipo de valor. As duas formas são intercambiáveis.
Embora concorde plenamente que na maioria dos casos eles são o mesmo, recentemente deparei com uma situação, quando não é a diferença entre os dois. Para os detalhes sangrentos, consulte esta pergunta , mas para dar um exemplo rápido aqui:
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
}
A primeira linha fornece as seguintes mensagens de erro:
error CS1003: Syntax error, ':' expected
error CS1525: Invalid expression term ';'
Se você está curioso sobre o motivo exato para isso, eu realmente recomendo que você verifique a questão já vinculada , mas o problema básico é que na fase de análise após um is(ou um as) operador, quando nos deparamos com um ?token, verificamos se o próximo token pode ser interpretado como um operador unário ( &poderia ser um) e se assim for: o analisador não se preocupa com a possibilidade de o ?token ser um modificador de tipo, ele simplesmente usa o tipo antes dele e irá analisar o resto como se o? token era um operador ternário (portanto, a análise falhará).
Portanto, embora em geral int?e Nullable<int>sejam intercambiáveis, existem alguns casos extremos em que eles produzem resultados completamente diferentes, devido à forma como o analisador vê seu código.
test,, é fixado com um parêntese, portanto var test = (a is int?) & b;. Também pode ser corrigido com var test = a is int? && b;, e dado que bé um parâmetro de valor simples (sem efeitos colaterais sobre a avaliação) parece estranho a preferir &mais &&.
?é um personagem-chave.
int?como uma operação ternária ( var test = a is int? <return if true> : <return if false>), não um int anulável.
boolsobrecargas específicas . Estes são operadores lógicos booleanos (o &for bool) e operadores lógicos condicionais booleanos (o &&for bool). Observe como a primeira dessas subseções é claramente chamada de lógica . Lembre-se, em C # não há conversões ("casts") entre boolos tipos numéricos!
Aparentemente, há uma diferença entre os dois ao usar a geração de Entity Framework (EF) de código primeiro:
Quando sua entidade contém uma propriedade declarada como:
public class MyEntity
{
public Nullable<int> MyNullableInt { get; set; }
}
EF não irá gerar uma propriedade anulável e você terá que forçar o gerador para torná-la anulável assim:
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();
}
}
Por outro lado, se você declarar sua entidade como:
public class MyEntity
{
public int? MyNullableInt { get; set; }
}
o gerador EF irá gerar uma propriedade anulável com um campo anulável na tabela de banco de dados correspondente.
Nullabledefinição em algum lugar, porque com o embutido Nullable<T>, não é possível para EF ver a diferença entre os dois. Mesmo que o pessoal da EF quisesse tratá-los de maneira diferente, eles não poderiam.
Nullable é um tipo genérico, mas int? não é.
Existem alguns cenários em que Nullable deve ser usado em vez de int?
por exemplo: aqui você não pode substituir Nullable por int?
como você pode alterar o código abaixo sem usar 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>