Видимо Nullable<int>и int?равнозначны по стоимости. Есть ли причины выбрать одно из них?
Nullable<int> a = null;
int? b = null;
a == b; // this is true
Видимо Nullable<int>и int?равнозначны по стоимости. Есть ли причины выбрать одно из них?
Nullable<int> a = null;
int? b = null;
a == b; // this is true
Ответы:
?Форма просто сокращение для полного типа. Личные предпочтения - единственная причина предпочесть одно другому.
Подробности здесь .
Синтаксис
T?является сокращением дляNullable<T>, гдеT- тип значения. Эти две формы взаимозаменяемы.
Хотя я полностью согласен с тем, что в большинстве случаев они одинаковы, недавно я столкнулся с ситуацией, когда между ними есть разница. Подробности см. В этом вопросе , но вот краткий пример:
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
}
Первая строка дает следующие сообщения об ошибках:
error CS1003: Syntax error, ':' expected
error CS1525: Invalid expression term ';'
Если вам интересно узнать точную причину этого, я действительно рекомендую вам проверить уже связанный вопрос , но основная проблема заключается в том, что на этапе синтаксического анализа после is(или as) оператора, когда мы сталкиваемся с ?токеном, мы проверяем, будет ли следующий токен можно интерпретировать как унарный оператор ( &может быть таковым), и если так: синтаксический анализатор не заботится о возможности того, что ?токен является модификатором типа, он просто использует тип перед ним и будет анализировать остальные, как если бы ?token были тернарным оператором (таким образом, синтаксический анализ не удастся).
Таким образом, в то время как в целом int?и Nullable<int>являются взаимозаменяемыми, есть некоторые частные случаи , когда они производят совершенно разные результаты, так как анализатор видит ваш код.
test,, фиксируется круглыми скобками, поэтому var test = (a is int?) & b;. Может быть исправлены с var test = a is int? && b;, и при условии , что bявляется параметром простого значения (отсутствие побочных эффектов по оценке), кажется странным, предпочитает &более &&.
?- ключевой символ.
int?как тернарная операция ( var test = a is int? <return if true> : <return if false>), а не как int, допускающий значение NULL.
boolперегрузкам. Это булевы логические операторы ( &for bool) и логические условные логические операторы ( &&for bool). Обратите внимание, что первый из этих подразделов четко назван логическим . Помните, что в C # нет преобразований ("приведений") между boolчисловыми типами и!
Очевидно, существует разница между ними при использовании генерации Entity Framework (EF) с первым кодом:
Когда ваша сущность содержит свойство, объявленное как:
public class MyEntity
{
public Nullable<int> MyNullableInt { get; set; }
}
EF не будет генерировать свойство, допускающее значение NULL, и вам придется заставить генератор сделать его допускающим значение NULL следующим образом:
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();
}
}
С другой стороны, если вы объявите свою сущность как:
public class MyEntity
{
public int? MyNullableInt { get; set; }
}
генератор EF создаст свойство, допускающее значение NULL, с полем, допускающим значение NULL, в соответствующей таблице базы данных.
Nullableопределение, потому что со встроенным Nullable<T>EF не может увидеть разницу между ними. Даже если бы люди из EF хотели относиться к ним по-другому, они не могли.
Nullable - это общий тип, но int? не является.
Есть несколько сценариев, в которых Nullable следует использовать вместо int?
например: здесь вы не можете заменить Nullable на int?
как вы можете изменить приведенный ниже код без использования 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>