Najwyraźniej Nullable<int>i int?mają równoważną wartość. Czy są jakieś powody, aby wybrać jeden z nich?
Nullable<int> a = null;
int? b = null;
a == b; // this is true
Najwyraźniej Nullable<int>i int?mają równoważną wartość. Czy są jakieś powody, aby wybrać jeden z nich?
Nullable<int> a = null;
int? b = null;
a == b; // this is true
Odpowiedzi:
?Forma jest po prostu skrótem dla pełnego typu. Osobiste preferencje to jedyny powód, aby wybrać jedną z nich.
Pełne szczegóły tutaj .
Składnia
T?jest skróconaNullable<T>, gdzieTjest typem wartości. Te dwie formy są wymienne.
A ja całkowicie zgadzam się, że w większości przypadków są one takie same, Niedawno natknąłem się na sytuacji, gdy nie jest różnica między tymi dwoma. Aby poznać krwawe szczegóły, zobacz to pytanie , ale aby dać ci szybki przykład tutaj:
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
}
Pierwsza linia zawiera następujące komunikaty o błędach:
error CS1003: Syntax error, ':' expected
error CS1525: Invalid expression term ';'
Jeśli ciekawi cię dokładny powód tego, naprawdę polecam sprawdzenie już połączonego pytania , ale podstawowym problemem jest to, że w fazie parsowania po operatorze is(lub as), gdy napotykamy ?token, sprawdzamy, czy następny token może być interpretowany jako operator jednoargumentowy ( &może być jednym), a jeśli tak: parser nie dba o możliwość, że ?token jest modyfikatorem typu, po prostu używa typu przed nim, a resztę przeanalizuje tak, jakby ?token był operatorem trójargumentowym (dlatego analiza nie powiedzie się).
Tak więc, chociaż ogólnie int?i Nullable<int>są wymienne, są pewne narożne przypadki, w których dają one zupełnie inne wyniki, z powodu tego, jak parser widzi twój kod.
test,, jest oznaczony nawiasem, więc var test = (a is int?) & b;. Może być również mocowane var test = a is int? && b;, i biorąc pod uwagę, że bjest to parametr wartość proste (bez skutków ubocznych na ocenę) wydaje dziwne wolą &ponad &&.
?jest kluczowym znakiem.
int?jako operację trójskładnikową ( var test = a is int? <return if true> : <return if false>), a nie int.
boolprzeciążeń. Są to logiczne operatory boolowskie ( &for bool) i warunkowe operatory logiczne boolowskie ( &&for bool). Zwróć uwagę, że pierwsza z tych podsekcji jest wyraźnie nazwana logiczną . Pamiętaj, że w C # nie ma konwersji („rzutów”) między booltypami numerycznymi!
Najwyraźniej istnieje różnica między nimi w przypadku korzystania z generowania Entity Framework (EF) w pierwszej kolejności:
Gdy Twój podmiot zawiera deklarowaną właściwość, taką jak:
public class MyEntity
{
public Nullable<int> MyNullableInt { get; set; }
}
EF nie wygeneruje właściwości dopuszczającej wartość null i będziesz musiał wymusić na generatorze, aby był on dopuszczalny w następujący sposób:
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();
}
}
Z drugiej strony, jeśli zadeklarujesz swój podmiot w następujący sposób:
public class MyEntity
{
public int? MyNullableInt { get; set; }
}
generator EF będzie generował właściwość dopuszczającą wartość null z polem dopuszczającym wartość null w odpowiedniej tabeli bazy danych.
Nullablegdzieś inną definicję, ponieważ przy wbudowanej Nullable<T>EF nie jest w stanie zobaczyć różnicy między nimi. Nawet jeśli pracownicy EF chcieli traktować ich inaczej, nie mogli.
Nullable to typ ogólny, ale int? nie jest.
Istnieje kilka scenariuszy, w których Nullable powinno być używane w int?
na przykład: tutaj nie można zastąpić pustych z int?
jak zmienić poniższy kod bez używania wartości 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>jestNullable<int>