Jakie jest pożądane zachowanie, kiedy v1jest null?
Solomon Ucko
Odpowiedzi:
637
Wszystkie dotychczasowe odpowiedzi są poprawne; Chciałem tylko dodać jeszcze jeden, który jest nieco czystszy:
v2 = v1 ??default(int);
Każde Nullable<T>jest domyślnie konwertowalne na jego T, ZAPEWNIONE, że całe oceniane wyrażenie nigdy nie może spowodować przypisania wartości NULL do ValueType. Tak więc operator zerowania koalescencyjnego ??jest po prostu cukrem składniowym dla operatora trójskładnikowego:
v2 = v1 ==null?default(int): v1;
... który z kolei jest składnią cukru dla if / else:
if(v1==null)
v2 =default(int);else
v2 = v1;
Ponadto, od .NET 4.0, Nullable<T>ma metodę „GetValueOrDefault ()”, która jest zerowo bezpiecznym narzędziem pobierającym, które zasadniczo wykonuje koalescencję zerową pokazaną powyżej, więc to też działa:
Czy default(int)naprawdę jest potrzebny? Co jest złego w prostym 0?
Cole Johnson
4
To zadziałałoby w tym przykładzie, ale w ogólnym przypadku zaleca się użycie w defaultrazie potrzeby. Zero nie zawsze jest poprawne jako wartość, a tym bardziej nie jest wartością domyślną, więc jeśli zamienisz intna ogólny, Tzauważysz, że mój kod działa, a zero nie. W niektórych przyszłych wersjach ramowych defaultmoże również stać się przeciążalny; jeśli i kiedy tak się stanie, kod korzystający z domyślnego kodu będzie mógł łatwo skorzystać, a jawne przypisania zerowe lub zerowe będą musiały zostać zmienione.
KeithS
5
Powinno to wzrosnąć do góry: .NET 4.0, Nullable <T> ma „GetValueOrDefault ()”
RandomHandle
Dziękujemy za powrót do edycji za pomocą GetValueOrDefault!
CindyH,
Podczas korzystania z wartości domyślnych warto zachować ostrożność podczas korzystania z funkcji DateTime. Może to wstawić domyślną datę zamiast pustej.
Ponadto - jeśli nie masz pewności, czy wersja 1 zawiera wartość null - możesz użyć operatora zerowania i koalescencji, aby ustawić wartość rezerwową. Np. V2 = v1 ?? 0;
Arjen
12
I v1.HasValuenajpierw sprawdź .
Fuj
3
MSDN mówi, że spowoduje to wyjątek, jeśli tak v1jest null. Moim zdaniem nie jest to poprawna odpowiedź.
ventiseis
6
@ventiseis Myślę, że to pożądane zachowanie - jestem zaskoczony, że wiele innych odpowiedzi jest w porządku, cicho przekształcając wartość zerową na 0. Jeśli przypisujesz typ zerowalny do typu, który nie ma wartości zerowej, powinieneś być pewien, że wartość nie jest faktycznie zerowa. OP nie powiedział: „Chcę przypisać v1 do v2 lub 0, jeśli v1 ma wartość zerową”, ale wszyscy tak zakładają
Jeśli wiesz, że v1ma wartość, możesz użyć Valuewłaściwości:
v2 = v1.Value;
Użycie GetValueOrDefaultmetody spowoduje przypisanie wartości, jeśli istnieje, w przeciwnym razie wartość domyślna dla typu lub wartość domyślna, którą określisz:
v2 = v1.GetValueOrDefault();// assigns zero if v1 has no value
v2 = v1.GetValueOrDefault(-1);// assigns -1 if v1 has no value
Możesz użyć HasValuewłaściwości, aby sprawdzić, czy v1ma wartość:
if(v1.HasValue){
v2 = v1.Value;}
Istnieje również obsługa języka dla tej GetValueOrDefault(T)metody:
Prosta konwersja między v1i v2nie jest możliwa, ponieważ v1ma większą domenę wartości niż v2. To wszystko v1może utrzymać plus nullpaństwo. Aby przekonwertować, musisz wyraźnie określić, jaka wartość intzostanie użyta do zmapowania nullstanu. Najprostszym sposobem na to jest ??operator
v2 = v1 ??0;// maps null of v1 to 0
Można to również zrobić w długiej formie
int v2;if(v1.HasValue){
v2 = v1.Value;}else{
v2 =0;}
W zależności od kontekstu użytkowania możesz użyć funkcji dopasowania wzorców w C # 7:
int? v1 =100;if(v1 isint v2){Console.WriteLine($"I'm not nullable anymore: {v2}");}
EDYTOWAĆ:
Ponieważ niektórzy ludzie oddają głos bez pozostawienia wyjaśnienia, chciałbym dodać kilka szczegółów wyjaśniających uzasadnienie włączenia tego jako realnego rozwiązania.
Dopasowywanie wzorców w C # 7 pozwala nam teraz sprawdzić typ wartości i rzucić ją niejawnie. W powyższym fragmencie warunek if przejdzie tylko wtedy, gdy przechowywana wartość v1jest zgodna z typem dla typu v2, czyli w tym przypadku int. Wynika z tego, że gdy wartość dla v1jest null, warunek if zakończy się niepowodzeniem, ponieważ nie można przypisać wartości null do zmiennej int. Mówiąc dokładniej, nullnie jest int.
Chciałbym podkreślić, że to rozwiązanie nie zawsze może być optymalnym wyborem. Jak sugeruję, uważam, że będzie to zależeć od dokładnego kontekstu użytkowania programisty. Jeśli masz już int?i chcesz warunkowo operować na jej wartości, jeśli-i-tylko-jeśli przypisana wartość nie jest równa null (jest to jedyny czas, kiedy można bezpiecznie przekonwertować dopuszczalną wartość int na zwykłą liczbę int bez utraty informacji), to dopasowanie wzorca jest prawdopodobnie jednym z najbardziej zwięzłych sposobów na zrobienie tego.
Konieczność wprowadzenia nowej nazwy zmiennej jest niefortunna, ale jest to najlepsze (najbezpieczniejsze) rozwiązanie, jeśli nie ma wartości domyślnej, ponieważ nie ma ryzyka przypadkowego refaktoryzacji HasValueczeków.
minexew
Po prostu nie widzę żadnej przewagi tej metody nad v1.HasValue jako czekiem, a następnie v1.Value, aby uzyskać dostęp do wartości bazowej. Nie głosowałbym za tym, ale myślę, że ten problem został już rozwiązany, a nowa technika nie dodaje mu większej przejrzystości. Testowałem go również jako 8-9% wolniejszy.
Brandon Barkley
Dziękujemy za przeprowadzenie testu porównawczego, to dobrze wiedzieć! Tak czy inaczej, różnica jest w najlepszym razie marginalna (chyba że zrobisz to w krytycznym dla siebie obszarze, jak sądzę). Patrzę na to, że jest to bardziej „zwięzłe” lub być może „idiomatyczne”, ponieważ opiera się na cukrach składniowych upieczonych w języku zamiast API. Jest to nieco subiektywne, ale może „łatwiejsze w utrzymaniu”. Chociaż tak naprawdę podoba mi się to podejście bardziej niż poleganie na wartości domyślnej, jak sugeruje wiele innych odpowiedzi.
Nicholas Miller
3
Przydzieli wartość v1do, v2jeśli nie jest zerowa, w przeciwnym razie przyjmie wartość domyślną jako zero.
W wersji C # 7.1 i nowszych typ można wywnioskować za pomocą defaultliterału zamiast defaultoperatora, dzięki czemu można go zapisać w następujący sposób:
Chociaż ten kod może odpowiedzieć na pytanie, zapewnienie dodatkowego kontekstu dotyczącego tego, dlaczego i / lub jak ten kod odpowiada na pytanie, poprawia jego długoterminową wartość.
Odpowiadając na ośmioletnie pytanie z piętnastoma istniejącymi odpowiedziami, ważne jest, aby wyjaśnić, jaki nowy aspekt pytania dotyczy twoja odpowiedź, i zauważyć, czy upływ czasu zmienił odpowiedź. Tylko odpowiedzi na kod można prawie zawsze poprawić, dodając pewne wyjaśnienia.
v1
jestnull
?Odpowiedzi:
Wszystkie dotychczasowe odpowiedzi są poprawne; Chciałem tylko dodać jeszcze jeden, który jest nieco czystszy:
Każde
Nullable<T>
jest domyślnie konwertowalne na jegoT
, ZAPEWNIONE, że całe oceniane wyrażenie nigdy nie może spowodować przypisania wartości NULL do ValueType. Tak więc operator zerowania koalescencyjnego??
jest po prostu cukrem składniowym dla operatora trójskładnikowego:... który z kolei jest składnią cukru dla if / else:
Ponadto, od .NET 4.0,
Nullable<T>
ma metodę „GetValueOrDefault ()”, która jest zerowo bezpiecznym narzędziem pobierającym, które zasadniczo wykonuje koalescencję zerową pokazaną powyżej, więc to też działa:źródło
default(int)
naprawdę jest potrzebny? Co jest złego w prostym0
?default
razie potrzeby. Zero nie zawsze jest poprawne jako wartość, a tym bardziej nie jest wartością domyślną, więc jeśli zamieniszint
na ogólny,T
zauważysz, że mój kod działa, a zero nie. W niektórych przyszłych wersjach ramowychdefault
może również stać się przeciążalny; jeśli i kiedy tak się stanie, kod korzystający z domyślnego kodu będzie mógł łatwo skorzystać, a jawne przypisania zerowe lub zerowe będą musiały zostać zmienione.Lubię to,
źródło
Do przypisania można użyć właściwości Value.
źródło
v1.HasValue
najpierw sprawdź .v1
jestnull
. Moim zdaniem nie jest to poprawna odpowiedź.Wszystko czego potrzebujesz to..
źródło
Jeśli wiesz, że
v1
ma wartość, możesz użyćValue
właściwości:Użycie
GetValueOrDefault
metody spowoduje przypisanie wartości, jeśli istnieje, w przeciwnym razie wartość domyślna dla typu lub wartość domyślna, którą określisz:Możesz użyć
HasValue
właściwości, aby sprawdzić, czyv1
ma wartość:Istnieje również obsługa języka dla tej
GetValueOrDefault(T)
metody:źródło
Nie możesz tego zrobić, jeśli wersja 1 ma wartość NULL, ale możesz to sprawdzić u operatora.
źródło
pobiera wartość obiektu. Jeśli ma wartość null, zwraca wartość domyślną int, która wynosi 0.
Przykład:
źródło
Jeśli wartość domyślna dla danego typu jest akceptowalnym wynikiem:
Jeśli chcesz inną wartość domyślną, gdy wynik jest niezdefiniowany:
Jeśli chcesz tylko zwrócić wartość (bez względu na to, czy metoda zawiodła, czy nie):
.NET 4.7.2 .:
GetValueOrDefault()
zwraca wartość pola bez sprawdzania.źródło
Moim zdaniem najlepszym rozwiązaniem jest użycie
GetValueOrDefault()
metody.źródło
Zamiana int nullable na int może być wykonana w następujący sposób:
źródło
jest to możliwe dzięki
v2 = Convert.ToInt32(v1);
źródło
Mógłbyś
źródło
Prosta konwersja między
v1
iv2
nie jest możliwa, ponieważv1
ma większą domenę wartości niżv2
. To wszystkov1
może utrzymać plusnull
państwo. Aby przekonwertować, musisz wyraźnie określić, jaka wartośćint
zostanie użyta do zmapowanianull
stanu. Najprostszym sposobem na to jest??
operatorMożna to również zrobić w długiej formie
źródło
W zależności od kontekstu użytkowania możesz użyć funkcji dopasowania wzorców w C # 7:
EDYTOWAĆ:
Ponieważ niektórzy ludzie oddają głos bez pozostawienia wyjaśnienia, chciałbym dodać kilka szczegółów wyjaśniających uzasadnienie włączenia tego jako realnego rozwiązania.
Dopasowywanie wzorców w C # 7 pozwala nam teraz sprawdzić typ wartości i rzucić ją niejawnie. W powyższym fragmencie warunek if przejdzie tylko wtedy, gdy przechowywana wartość
v1
jest zgodna z typem dla typuv2
, czyli w tym przypadkuint
. Wynika z tego, że gdy wartość dlav1
jestnull
, warunek if zakończy się niepowodzeniem, ponieważ nie można przypisać wartości null do zmiennejint
. Mówiąc dokładniej,null
nie jestint
.Chciałbym podkreślić, że to rozwiązanie nie zawsze może być optymalnym wyborem. Jak sugeruję, uważam, że będzie to zależeć od dokładnego kontekstu użytkowania programisty. Jeśli masz już
int?
i chcesz warunkowo operować na jej wartości, jeśli-i-tylko-jeśli przypisana wartość nie jest równa null (jest to jedyny czas, kiedy można bezpiecznie przekonwertować dopuszczalną wartość int na zwykłą liczbę int bez utraty informacji), to dopasowanie wzorca jest prawdopodobnie jednym z najbardziej zwięzłych sposobów na zrobienie tego.źródło
HasValue
czeków.Przydzieli wartość
v1
do,v2
jeśli nie jest zerowa, w przeciwnym razie przyjmie wartość domyślną jako zero.Lub poniżej jest inny sposób, aby to napisać.
źródło
W wersji C # 7.1 i nowszych typ można wywnioskować za pomocą
default
literału zamiastdefault
operatora, dzięki czemu można go zapisać w następujący sposób:źródło
źródło