Pytanie Nullable vs. int? - Czy jest jakaś różnica?


Widocznie Nullable<int> i int? są równoważne pod względem wartości. Czy są jakieś powody, aby wybrać jedną z drugą?

Nullable<int> a = null;
int? b = null;
a == b; // this is true

76
2017-10-26 23:14


pochodzenie




Odpowiedzi:


Bez różnicy.

int? jest tylko skrótem Nullable<int>, który sam w sobie jest skrótem Nullable<Int32>.

Skompilowany kod będzie dokładnie taki sam, jaki wybierzesz.


113
2017-10-26 23:16



... chyba że używasz najpierw kodu EF. Zobacz moją odpowiedź poniżej. - Maciej
Niestety są pewne przypadki narożne, gdy nie jest to ściśle prawda. Zobacz odpowiedź. - qqbenq


The ? Formularz jest skrótem dla pełnego typu. Osobiste preferencje to jedyny powód, aby wybrać jeden z nich.

Pełne szczegóły tutaj.

Składnia T? jest skrótem dla    Nullable<T>, gdzie T jest typem wartości.   Te dwie formy są wymienne.


20
2017-10-26 23:17



... lub czytelność. - adrianbanks
@adrianbanks - na pewno - Steve Townsend


Chociaż całkowicie zgadzam się, że w większości przypadków są one takie same, ostatnio natknąłem się na sytuację, kiedy tam jest jest różnica między tymi dwoma. Aby poznać szczegóły, zobacz to pytanie, ale żeby 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
}

Pierwszy wiersz zawiera następujące komunikaty o błędach:

error CS1003: Syntax error, ':' expected 
error CS1525: Invalid expression term ';'

Jeśli interesuje Cię dokładny powód tego, naprawdę polecam sprawdzenie już powiązane pytanie, ale podstawowym problemem jest to, że w fazie analizy po is (lub as) operator, gdy mamy do czynienia z a ? token sprawdzamy czy Kolejny znak mogą być interpretowane jako operator jednoargumentowy (& może być jeden), a jeśli tak, to: parser nie dba o możliwość ? token jest modyfikatorem typu, po prostu używa typu przed nim i parsuje resztę, jak gdyby ? token był operatorem potrójnym (a więc przetwarzanie zakończy się niepowodzeniem).

Tak więc, podczas gdy w ogóle int? i Nullable<int> są wymienne, są pewne przypadki narożne, gdy dają zupełnie inne wyniki, z uwagi na to, jak analizator analizuje twój kod.


16
2017-07-14 14:03



Pierwszy przypadek, test, jest ustalony za pomocą nawiasu, czyli var test = (a is int?) & b;. Można również naprawić za pomocą var test = a is int? && b;i biorąc pod uwagę to b jest prostym parametrem wartości (nie ma efektów ubocznych w ocenie), wydaje się dziwne &koniec &&. - Jeppe Stig Nielsen
W tej konkretnej składni, ? jest kluczową postacią. - Pete Garafano
Zobacz powiązane pytanie i odpowiedź, twoje komentarze są tam adresowane :) Właśnie dodałem tę informację tutaj, ponieważ uznałem, że jest to istotne, ponieważ ujawnia różnicę między tymi dwiema formami, i dowodzi, że to nie jest tylko cukier syntaktyczny - qqbenq
Jeppe ma rację. Nie kompiluje się, ponieważ interpretuje int? jako operacja trójskładnikowa (var test = a is int? <return if true> : <return if false>), a nie interem nullable. - Levi Fuller
Również @ Jeppe ... & jest bitowym ORAZ while && jest operatorem logicznym. Na przykład ocenia wynik bit-na-bit ... (<dziesiętny> == <binarny>) 1 == 01 & 2 == 10... (1 & 2) == 0 - Levi Fuller


Najwyraźniej istnieje różnica między tymi dwoma przy użyciu generowania kodu Entity Framework (EF):

Kiedy twój podmiot zawiera właściwość zadeklarowaną jak:

public class MyEntity
{
    public Nullable<int> MyNullableInt { get; set; } 
}

EF nie wygeneruje właściwości zerowującej i będziesz musiał wymusić generator, aby uczynić go zerowalnym, jak na przykład:

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 jak:

public class MyEntity
{
     public int? MyNullableInt { get; set; }
}

generator EF będzie generował właściwość zerowalną z polem zerowym w odpowiedniej tabeli bazy danych.


4
2018-06-05 14:06



To naprawdę niefortunne. - siride
To sugeruje, że masz inne Nullable definicja gdzieś, ponieważ z wbudowanym Nullable<T>, EF nie może zobaczyć różnicy między tymi dwoma. Nawet jeśli ludzie z EF chcieli traktować ich inaczej, nie mogli. - hvd
Czy ktoś to potwierdził? (tylko trochę ostrożny z powodu negatywnych głosów) - RayLoveless
@RayL Nie, tak nie jest. Ta odpowiedź nie jest poprawna i jak wskazał hvd, niemożliwe. - Shoe
Biorąc pod uwagę, że kod EF jest generowany przy użyciu szablonów kodów, może to faktycznie być możliwe. Moja odpowiedź opiera się na moim doświadczeniu, a zaproponowana przeze mnie zmiana rozwiązała problem, który miałem. Wygląda też na to, że niektórzy ludzie stwierdzili, że tak naprawdę jest w przypadku głosów upowych. - Maciej


Nullable jest typem ogólnym, ale int? nie jest.

Istnieje kilka scenariuszy, w których Nullable powinien zostać użyty int?

na przykład: tutaj nie można zastąpić Nullable z int? 

jak zmienić poniższy kod bez użycia 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;
      }
   }
}

1
2017-07-30 23:32



private T? val działa dobrze. - johnnyRose
Co może mieć znaczenie, jeśli pytanie dotyczyło typów ogólnych, ale pytanie określało int, więc nie jest Nullable<T> jego Nullable<int> - Andrew