?: ?? Operatory zamiast IF | ELSE

85
public string Source
{
    get
    {
        /*
        if ( Source == null ){
            return string . Empty;
        } else {
            return Source;
        }
        */
        return Source ?? string.Empty;
    }
    set
    {
        /*
        if ( Source == null ) {
            Source = string . Empty;
        } else {
            if ( Source == value ) {
                Source = Source;
            } else {
                Source = value;
            }
        }
        */
        Source == value ? Source : value ?? string.Empty;
        RaisePropertyChanged ( "Source" );
    }
}

Czy mogę używać ?: ??operatorów DOKŁADNIE jako Jeśli / Inaczej?


Moje pytanie:
Jak napisać to za pomocą?: ?? operatorów

[1]

if ( Source == null ){
    // Return Nothing
} else {
    return Source;
}

[2]

if ( Source == value ){
    // Do Nothing
} else {
    Source = value;
    RaisePropertyChanged ( "Source" );
} 

W skrócie : jak nic nie robić, nic nie zwracać i wykonywać wiele instrukcji z ?: ??operatorem?

Ahmed Ghoneim
źródło
1
Jednak nie będzie zachowywać się tak samo. Nie używając warunkowego rozgałęziania if / else, bezwarunkowo (i niepotrzebnie) ponownie przypisujesz zmienną za każdym razem, gdy uzyskujesz do niej dostęp. Może to bardzo szybko się zepsuć, zwłaszcza jeśli masz kod wielowątkowy. Po prostu tego nie rób.
Jeff Mercado
1
Będziesz mieć wywołanie niekończące się / rekurencyjne, jeśli metoda dostępu get właściwości Source zwraca właściwość Source (jej akcesor get).
John K
1
Twój pierwszy fragment kodu ma właściwość pobierającą, która wywołuje swój własny ustawiający , który z kolei rekurencyjnie wywołuje swój własny moduł pobierający . Straciłeś mnie tam, bo nie ma mowy, żeby coś takiego działało w terenie. Sprecyzuj swoje pytanie i wyjaśnij dokładnie, co chcesz osiągnąć.
Frédéric Hamidi
Nic nie zwracać? To jest VB. Piszesz c # tutaj.
Zadanie
@Task Chodzi mi o to, jak to zrobić, ta linia jest komentarzem do pytania
Ahmed Ghoneim

Odpowiedzi:

198

W przypadku [1] nie możesz: te operatory mają zwracać wartość, a nie wykonywać operacji.

Ekspresja

a ? b : c

oblicza, że bjeśli ajest prawdą i oblicza, że cjeśli ajest fałszem.

Ekspresja

b ?? c

szacuje, że bif bnie jest null, i oblicza, że cif bjest null.

Jeśli piszesz

return a ? b : c;

lub

return b ?? c;

będą zawsze coś zwrócić.

W przypadku [2] możesz napisać funkcję, która zwraca właściwą wartość, która wykonuje Twoje „operacje wielokrotne”, ale jest to prawdopodobnie gorsze niż zwykłe używanie if/else.

prawdomówność
źródło
41

Operator trójargumentowy ( ?:) nie jest przeznaczony do sterowania przepływem , jest przeznaczony tylko do przypisywania warunkowego . Jeśli chcesz kontrolować przepływ swojego programu, użyj struktury kontrolnej, takiej jak if/ else.

Oliver Charlesworth
źródło
5
Dodam, że widziałem ludzi używających zagnieżdżonych wyrażeń trójskładnikowych zamiast if / else i tworzyło kod, który jest trudny do odczytania i debugowania. Złe mojo dookoła.
ckramer
4
Czasami zagnieżdżone operatory trójskładnikowe tworzą bardziej czytelny kod, jeśli białe znaki są używane prawidłowo.
trutheality
2
@truth: Tak, nie mam nic przeciwko zagnieżdżeniu jako takiego ?:. Ale mam duży problem z tym, że są używane do sterowania przepływem, a zwłaszcza zagnieżdżonym przepływem sterowania!
Oliver Charlesworth
11

Odnosząc się do ?: Operator (odwołanie w C #)

Operator warunkowy (? :) zwraca jedną z dwóch wartości w zależności od wartości wyrażenia boolowskiego. Poniżej znajduje się składnia operatora warunkowego.

Odnosząc się do ?? Operator (odwołanie w C #) Operator (C # Reference)

?? Operator jest nazywany operatorem łączenia wartości null i służy do definiowania wartości domyślnej dla typów wartości dopuszczających wartość null, a także typów odwołań. Zwraca operand po lewej stronie, jeśli nie jest pusty; w przeciwnym razie zwraca prawy operand.

To znaczy:

[Część 1]

return source ?? String.Empty;

[Część 2] nie ma zastosowania ...

Akram Shahda
źródło
3
To różni się od robienia niczego. Zwraca pusty ciąg.
prawdomówność
1
Jasne, ale nie o to prosił OP. To nie moja wina, że ​​OP zażądał „niczego nie zwracać” - cokolwiek to może oznaczać.
trutheality
1
@trutheality: Nikt nie powiedział, że to twoja wina .. Jednak OP nie chciał nic zwrócić i to, co zapewniłem.
Akram Shahda
3

„Nic nie rób” tak naprawdę nie działa?

if przez // Return Nic, co właściwie masz na myśli, return null to napisz

return Source;

jeśli masz na myśli, zignoruj ​​ścieżkę kodu, a następnie napisz

 if ( Source != null )
            {
                return Source;
            }
// source is null so continue on.

I na koniec

 if ( Source != value )
            { Source = value;
                RaisePropertyChanged ( "Source" );
            }

// nothing done.
Vinnyq12
źródło
3

Operator trójargumentowy ZWRACA jedną z dwóch wartości. Lub może wykonać jedną z dwóch instrukcji na podstawie swojego stanu, ale generalnie nie jest to dobry pomysł, ponieważ może prowadzić do niezamierzonych skutków ubocznych.

bar ? () : baz();

W tym przypadku () nic nie robi, podczas gdy baz coś robi. Ale tylko uczyniłeś kod mniej przejrzystym. Wybrałbym bardziej szczegółowy kod, który jest jaśniejszy i łatwiejszy w utrzymaniu.

Co więcej, nie ma to w ogóle sensu:

var foo = bar ? () : baz();

ponieważ () nie ma typu zwracanego (jest void), a baz ma typ zwracany, który jest nieznany w momencie wywołania w tym przykładzie. Jeśli się nie zgodzą, kompilator będzie głośno narzekał.

Mike Hofer
źródło
2

Jeśli martwisz się szczegółowością twojego kodu, napiszę to, zamiast próbować nadużywać wyrażeń.

if (Source == value) return;
Source = value;
RaisePropertyChanged("Source");
ChaosPandion
źródło
Nie nadużywam wyrażeń, po prostu myślę!
Ahmed Ghoneim
1

?: jest operatorem trasy. (uwierz, że poprawnie to przeliterowałem) i jest prosty w użyciu. jak w predykacie boolowskim? iftrue: ifalse; Ale musisz mieć rvalue / lvalue jak w rvalue = predicate? iftrue: iffalse;

dawny int i = x < 7 ? x : 7;

jeśli x było mniejsze niż 7, zostałbym przypisany x, jeśli nie, byłbym 7.

możesz również użyć go w zamian, jak w return x < 7 ? x : 7;

ponownie, jak powyżej, miałoby to taki sam wpływ.

więc Source = Source == value ? Source : string.Empty;wierzę , że to jest to, co próbujesz osiągnąć.

johnathan
źródło
6
Lubię to. Trasa operator : pomaga dostać z punktu A do punktu B ... lub od A do C ... w zależności od A.
Rick Sladkeya
Tak, ma na myśli trójskładnik. Ale poprawna nazwa to „warunkowa”.
Erick G. Hagstrom
1

?:Operator zwraca jedną z dwóch wartości w zależności od wartości Boolean wypowiedzi.

Condition-Expression ? Expression1 : Expression2

Dowiedz się więcej o ?:operatorze, znanym również jako operator trójskładnikowy:

rudenaggar
źródło
0

Nie sądzę, żebyś mógł to być operatorem i przypuszcza, że ​​zwróci jeden lub drugi. To nie jest zamiana instrukcji if else, chociaż można jej użyć do tego w niektórych przypadkach.

atbebtg
źródło