Co oznaczają dwa znaki zapytania razem w C#?

Przebiegał przez tę linijkę kodu:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

Co oznaczają te dwa znaki zapytania, czy to jakiś operator trójkowy? Ciężko to sprawdzić w Google.

Author: Igor Kustov, 2009-01-15

18 answers

Jest operatorem koalescencyjnym zerowym, podobnie jak operator trójkowy (immediate-if). Zobacz też ?? Operator-MSDN .

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

Rozszerza się do:

FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();

Który dalej rozszerza się na:

if(formsAuth != null)
    FormsAuth = formsAuth;
else
    FormsAuth = new FormsAuthenticationWrapper();

W języku angielskim oznacza "jeśli to, co jest po lewej nie jest null, użyj tego, w przeciwnym razie użyj tego, co jest po prawej."

Zauważ, że możesz użyć dowolnej ich liczby w sekwencji. Poniższe polecenie przypisze pierwszą Nie-null Answer# do Answer (jeśli wszystkie odpowiedzi są null wtedy Answer jest null):

string Answer = Answer1 ?? Answer2 ?? Answer3 ?? Answer4;

Warto również wspomnieć o tym, że powyższe rozwinięcie jest koncepcyjnie równoważne, wynik każdego wyrażenia jest oceniany tylko raz. Jest to ważne, jeśli na przykład wyrażenie jest wywołaniem metody z efektami ubocznymi. (Kredyt dla @ Joey za wskazanie tego.)

 2297
Author: lc.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-11 11:19:08

Tylko dlatego, że nikt inny nie wypowiedział jeszcze magicznych słów: jest to operator koalescencyjny zerowy . Jest zdefiniowany w sekcji 7.12 specyfikacji języka C # 3.0 .

Jest bardzo poręczny, szczególnie ze względu na sposób, w jaki działa, gdy jest używany wiele razy w wyrażeniu. Wyrażenie postaci:

a ?? b ?? c ?? d

Da wynik wyrażenia a jeśli nie jest null, w przeciwnym razie try b, w przeciwnym razie try c, w przeciwnym razie try d. Zwarcie w każdym punkt.

Również, jeśli Typ d jest nie-nullable, to typ całego wyrażenia jest również nie-nullable.

 297
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-08 16:08:19

Jest operatorem koalescencji zerowej.

Http://msdn.microsoft.com/en-us/library/ms173224.aspx

Tak, prawie niemożliwe do wyszukania, chyba że wiesz, jak to się nazywa! :-)

EDIT: a to jest fajna funkcja z innego pytania. Możesz je skuć.

Ukryte cechy C#?

 71
Author: Iain Holder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:48

Dzięki wszystkim, oto najbardziej zwięzłe wyjaśnienie, jakie znalazłem na stronie MSDN:

// y = x, unless x is null, in which case y = -1.
int y = x ?? -1;
 29
Author: Edward Tanguay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-05 13:37:09

Tutaj wpisz opis obrazka

Dwa znaki zapytania (??) wskazują, że jest to operator koalescencyjny.

Operator koalescencyjny zwraca pierwszą wartość inną niż NULL z łańcucha. Możesz zobaczyć ten filmik na youtube , który praktycznie pokazuje całość.

[7]}ale pozwól, że dodam więcej do tego, co mówi film.

Jeśli widzisz angielskie znaczenie łączenia, to znaczy "konsolidować razem". Na przykład poniżej znajduje się prosty kod łączący cztery łańcuchy.

Więc jeśli str1 jest null spróbuje str2, Jeśli str2 jest null spróbuje str3 itd., dopóki nie znajdzie ciągu z wartością inną niż null.

string final = str1 ?? str2 ?? str3 ?? str4;

W prostych słowach operator koalescencyjny zwraca pierwszą wartość inną niż NULL z łańcucha.

 25
Author: Shivprasad Koirala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-09 16:02:41

?? czy można podać wartość dla typu nullable, gdy wartość jest null. Tak więc, jeśli formsAuth jest równe null, zwróci nowe FormsAuthenticationWrapper ().

 22
Author: D'Arcy Rittich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-04 08:26:11

To krótka ręka dla operatora trójdzielnego.

FormsAuth = (formsAuth != null) ? formsAuth : new FormsAuthenticationWrapper();

Lub dla tych, którzy nie robią trójki:

if (formsAuth != null)
{
  FormsAuth = formsAuth;
}
else
{
  FormsAuth = new FormsAuthenticationWrapper();
}
 14
Author: Benjamin Autin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-15 14:09:34

Jeśli znasz Ruby, jego ||= wydaje mi się zbliżony do C#'S ??. Tu jest jakiś Ruby:

irb(main):001:0> str1 = nil
=> nil
irb(main):002:0> str1 ||= "new value"
=> "new value"
irb(main):003:0> str2 = "old value"
=> "old value"
irb(main):004:0> str2 ||= "another new value"
=> "old value"
irb(main):005:0> str1
=> "new value"
irb(main):006:0> str2
=> "old value"

I w C#:

string str1 = null;
str1 = str1 ?? "new value";
string str2 = "old value";
str2 = str2 ?? "another new value";
 12
Author: Sarah Vessels,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-30 17:16:22

Operator koalescencyjny

Jest odpowiednikiem

FormsAuth = formsAUth == null ? new FormsAuthenticationWrapper() : formsAuth
 11
Author: aku,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-04 08:25:51

Nie ma w tym nic niebezpiecznego. W rzeczywistości jest piękny. Możesz dodać wartość domyślną, jeśli jest to pożądane, na przykład:

Kod

int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;
 11
Author: dqninh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-21 21:40:37

Jak słusznie wskazano w licznych odpowiedziach, że jest "operatorem zerowym" (??), A skoro o tym mowa, warto też sprawdzić jego kuzyna "Operator warunkowy Null" (?. Czy ?[) czyli operator, który wielokrotnie jest używany w połączeniu z ??

Null-Operator warunkowy

Używany do testowania null przed wykonaniem dostępu członka (?.) lub index (?[) działanie. Te operatory pomagają w pisaniu mniej kodu do obsługi sprawdzeń null, szczególnie w przypadku wchodzenia do struktur danych.

Na przykład:

// if 'customers' or 'Order' property or 'Price' property  is null,
// dollarAmount will be 0 
// otherwise dollarAmount will be equal to 'customers.Order.Price'

int dollarAmount = customers?.Order?.Price ?? 0; 

Stara Droga bez ?. i ?? robienie tego jest

int dollarAmount = customers != null 
                   && customers.Order!=null
                   && customers.Order.Price!=null 
                    ? customers.Order.Price : 0; 
Co jest bardziej gadatliwe i uciążliwe.
 11
Author: brakeroo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-30 02:43:50

Tylko dla Twojej rozrywki (wiedząc, że wszyscy jesteście C # guys ;-).

Myślę, że pochodzi z Smalltalk, gdzie istnieje od wielu lat. Jest tam zdefiniowany jako:

W Obiekcie:

? anArgument
    ^ self

In UndefinedObject (aka nil ' S class):

? anArgument
    ^ anArgument

Są obie oceny (?) i wersje nieoceniające (??) tego.
jest to często spotykane w getter-methods dla leniwie inicjalizowanych zmiennych prywatnych (instancji), które pozostają zerowe do momentu, gdy są naprawdę potrzebne.

 10
Author: blabla999,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-15 14:31:04

Uwaga:

Przeczytałem cały ten wątek i wiele innych, ale nie mogę znaleźć tak dokładnej odpowiedzi, jak to jest.

Przez co całkowicie zrozumiałem "dlaczego używać ?? a kiedy używać ?? i jak używać ??."

źródło:

Windows communication foundation unleashed by Craig McMurtry ISBN 0-672-32948-4

Typy Wartości Nullable

Istnieją dwie wspólne okoliczności, w których ktoś chciałby wiedzieć, czy wartość został przypisany do instancji typu value. Pierwsza dotyczy sytuacji, gdy instancja reprezentuje wartość w bazie danych. W takim przypadku chcielibyśmy mieć możliwość zbadania instancji w celu ustalenia, czy dana wartość rzeczywiście jest obecna w bazie danych. Inną okolicznością, która jest bardziej istotna dla przedmiotu tej książki, jest sytuacja, gdy instancja reprezentuje element danych otrzymany z jakiegoś odległego źródła. Ponownie, chcielibyśmy ustalić z instancji, czy wartość dla tej pozycji danych jest przyjąłem.

. NET Framework 2.0 zawiera generyczną definicję typu, która przewiduje przypadki takie jak te, w których chce się przypisać NULL do instancji typu value i sprawdzić, czy jej wartość jest null. Ta ogólna definicja typu to System.Nullable<T>, która ogranicza argumenty typu ogólnego, które mogą być zastąpione przez T, do typów wartości. Instancjom typów zbudowanych z System.Nullable<T> można przypisać wartość null; w rzeczywistości ich wartości są domyślnie równe null. Tak więc rodzaje zbudowany z System.Nullable<T> mogą być określane jako typy wartości nullable. System.Nullable<T> posiada właściwość Value, przez którą wartość przypisana do instancji Typ zbudowany z niego można uzyskać, jeśli wartość instancji nie jest null. Dlatego można napisać:

System.Nullable<int> myNullableInteger = null;
myNullableInteger = 1;
if (myNullableInteger != null)
{
Console.WriteLine(myNullableInteger.Value);
}

Język programowania C# dostarcza skróconą składnię do deklarowania typów zbudowany z System.Nullable<T>. Składnia ta pozwala na skrócenie:

System.Nullable<int> myNullableInteger;

Do

int? myNullableInteger;

Kompilator zapobiegnie próbom aby przypisać wartość typu nullable do zwykłego typu wartości w ten sposób:

int? myNullableInteger = null;
int myInteger = myNullableInteger;

Uniemożliwia to, ponieważ typ wartości nullable może mieć wartość null, którą w rzeczywistości miałby w tym przypadku, a tej wartości nie można przypisać do zwykłego typu wartości. Chociaż kompilator zezwalałby na ten kod,

int? myNullableInteger = null;
int myInteger = myNullableInteger.Value;

Drugie stwierdzenie spowodowałoby wyrzucenie wyjątku, ponieważ każda próba dostęp do System.Nullable<T>.Właściwość Value jest nieprawidłową operacją jeśli Typ skonstruowany z System.Nullable<T> nie otrzymał ważnej wartości T, co w tym przypadku nie miało miejsca.

wniosek:

Jednym z właściwych sposobów przypisania wartości typu nullable do zwykłego typu wartości jest użycie System.Nullable<T>.Właściwość HasValue sprawdzająca, czy do typu nullable value została przypisana prawidłowa wartość T:

int? myNullableInteger = null;
if (myNullableInteger.HasValue)
{
int myInteger = myNullableInteger.Value;
}

Inną opcją jest użycie tej składni:

int? myNullableInteger = null;
int myInteger = myNullableInteger ?? -1;

Przy pomocy której przypisana jest zwykła liczba całkowita myInteger wartość nullable integer" myNullableInteger", Jeśli temu ostatniemu przypisano poprawną wartość całkowitą; w przeciwnym razie, myInteger zostanie przypisana wartość -1.

 10
Author: Muhammad Waqas Dilawar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-09 00:10:11

Niektóre przykłady uzyskiwania wartości za pomocą koalescencji są nieefektywne.

To czego naprawdę chcesz to:

return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();

Lub

return _formsAuthWrapper ?? (_formsAuthWrapper = new FormsAuthenticationWrapper());

Uniemożliwia to odtworzenie obiektu za każdym razem. Zamiast prywatnej zmiennej pozostającej null i tworzonego nowego obiektu przy każdym żądaniu, zapewnia to, że prywatna zmienna zostanie przyszeregowana, jeżeli nowy obiekt zostanie wytworzony.

 9
Author: KingOfHypocrites,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-15 20:28:17

Inni opisali Null Coalescing Operator dość dobrze. W przypadkach, gdy wymagany jest pojedynczy test dla null, skrócona składnia ??= może zwiększyć czytelność.

Test Legacy null:

if (myvariable == null)
{
    myvariable = new MyConstructor();
}

Używając operatora null można zapisać:

myvariable = myvariable ?? new MyConstructor();

Które można również zapisać skróconą składnią:

myvariable ??= new MyConstructor();

Niektórzy uważają, że jest bardziej czytelny i zwięzły.

 2
Author: Thane Plummer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-08 15:41:17

Jest operatorem koalescencyjnym null, który działa podobnie do operatora trójdzielnego.

    a ?? b  => a !=null ? a : b 

Kolejnym interesującym punktem jest, "Typ nullable może zawierać wartość lub może być niezdefiniowany" . Więc jeśli spróbujesz przypisać typ wartości nullable do typu wartości nie-nullable otrzymasz błąd w czasie kompilacji.

int? x = null; // x is nullable value type
int z = 0; // z is non-nullable value type
z = x; // compile error will be there.
Więc, żeby to zrobić używając ?? operator:
z = x ?? 1; // with ?? operator there are no issues
 1
Author: Ashish Mishra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-27 12:22:33
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

Jest równoważne

FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();
Ale najfajniejsze w tym jest to, że możesz je łańcuchować, tak jak mówili inni. Jedynym cienkim, którego nie dotknięto, jest to, że możesz go użyć do rzucenia wyjątku.
A = A ?? B ?? throw new Exception("A and B are both NULL");
 1
Author: NolePTR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-31 21:22:46

Operator ?? nazywany jest operatorem koalescencyjnym null. Zwraca operand lewostronny, jeśli operand nie jest null; w przeciwnym razie zwraca operand prawostronny.

int? variable1 = null;
int variable2  = variable1 ?? 100;

Ustaw variable2 na wartość variable1, Jeśli variable1 NIE JEST null; w przeciwnym razie, Jeśli variable1 == null, ustaw variable2 na 100.

 1
Author: Jubayer Hossain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-06 11:36:56