?: ?? Оператори замість 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" );
    }
}

Чи можу я використовувати ?: ??оператори ТОЧНО як If / Else?


Моє запитання:
Як написати наступне за допомогою?: ?? операторів

[1]

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

[2]

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

Коротко : Як нічого не робити, нічого не повертати та виконувати кілька операцій з ?: ??оператором?


1
Однак він не буде поводитися так само. Не використовуючи умовне розгалуження if / else, ви безумовно (і без потреби) перепризначаєте змінну кожного разу, коли отримуєте до неї доступ. Це може дуже швидко зіпсуватися, особливо якщо у вас багатопотоковий код. Тільки не роби цього.
Джефф Меркадо,

1
Ви отримаєте нескінченний / рекурсивний виклик, якщо пристрій доступу get ресурсу Source повертає властивість Source (його access access).
John K

1
Ваш перший фрагмент коду має властивість getter, яка викликає власний сеттер , який, у свою чергу, рекурсивно викликає власний getter . Ви мене там загубили, оскільки немає можливості, щоб щось подібне могло спрацювати в полі. Будь ласка, уточніть своє запитання та поясніть, чого саме ви хочете досягти.
Фредерік Хаміді

Повернути нічого? Це VB. Ви пишете тут c #.
Завдання

@Task Я маю на увазі, як це зробити, цей рядок є коментарем до питання
Ахмед Гонейм

Відповіді:


198

Для [1] ви не можете: ці оператори створені для повернення значення, а не для виконання операцій.

Вираз

a ? b : c

обчислює bякщо aістинно та обчислює cякщо aнеправда.

Вираз

b ?? c

обчислює, bякщо bне є нульовим, і обчислює, cякщо bє нульовим.

Якщо ви пишете

return a ? b : c;

або

return b ?? c;

вони завжди щось повернуть.

Для [2] ви можете написати функцію, яка повертає правильне значення, яке виконує ваші "кілька операцій", але це, мабуть, гірше, ніж просто використання if/else.


41

Трійковий оператор ( ?:) не призначений для управління потоком , він призначений лише для умовного присвоєння . Якщо вам потрібно керувати потоком вашої програми, використовуйте структуру управління, таку як if/ else.


5
Додам, що я бачив, як люди використовують вкладені трійкові вирази замість if / else, і він видає важкий для читання код та налагоджує. Погане моджо навколо.
ckramer

4
Іноді вкладені тернарні оператори видають більш читабельний код, якщо пробіли використовуються належним чином.
правдивість

2
@truth: Так, я нічого не маю проти вкладеного ?:як такого. Але у мене є велика проблема з тим, що вони використовуються для управління потоком, і особливо вкладеного потоку управління!
Олівер Чарлсворт,

11

Посилаючись на ?: Оператор (Довідка C #)

Умовний оператор (? :) повертає одне з двох значень залежно від значення логічного виразу. Далі наведено синтаксис умовного оператора.

Посилаючись на ?? Оператор (посилання на C #)

?? Оператор називається оператором коалесценції з нулем і використовується для визначення значення за замовчуванням для типів значень, що допускають нульове значення, а також типів посилань. Він повертає лівий операнд, якщо він не має значення null; інакше повертає правильний операнд.

Це означає:

[Частина 1]

return source ?? String.Empty;

[Частина 2] не застосовується ...


3
Це відрізняється від нічого не робити. Повертає порожній рядок.
правдивість

1
Звичайно, але це не те, про що просив ОП. Я не винен, що ОП просив "нічого не повертати" - що б це не могло означати.
правдивість

1
@ правдивість: Жодне тіло не заявило, що це ваша вина. Однак ОП не хотів нічого повернути, і те, що я надав.
Акрам Шахда,

3

"Нічого не робити" насправді не працює?

якщо під // Повернути нічого ви насправді маєте на увазі повернути нуль, тоді напишіть

return Source;

якщо ви маєте на увазі, ігноруйте шлях шляху, а потім напишіть

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

І останнє

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

// nothing done.

3

Трійковий оператор ВЕРНУЄ одне з двох значень. Або він може виконати одне з двох тверджень, виходячи зі свого стану, але це, як правило, не є гарною ідеєю, оскільки це може призвести до небажаних побічних ефектів.

bar ? () : baz();

У цьому випадку () нічого не робить, тоді як baz щось робить. Але ви лише зробили код менш зрозумілим. Я б запропонував більш детальний код, який є зрозумілішим і простішим в обслуговуванні.

Далі, це взагалі мало сенсу:

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

оскільки () не має типу повернення (це недійсне значення), а baz має тип повернення, який невідомий на момент виклику в цьому зразку. Якщо вони не погоджуються, упорядник скаржиться і голосно.


2

Якщо вас турбує багатослівність вашого коду, я б писав це, а не намагався зловживати виразами.

if (Source == value) return;
Source = value;
RaisePropertyChanged("Source");

Я не зловживаю виразами, я просто думаю!
Ахмед Гонейм

1

оператор маршруту? (вважаю, що я написав це правильно), і він простий у використанні. як у логічному предикаті? iftrue: ifalse; Але ви повинні мати значення rvalue / lvalue як у rvalue = предикат? iftrue: iffalse;

напр int i = x < 7 ? x : 7;

якби х було менше 7, я отримав би присвоєний х, якщо ні, то був би 7.

Ви також можете використовувати його у відповідь, як у return x < 7 ? x : 7;

знову ж, як і вище, це мало б такий самий ефект.

отже, Source = Source == value ? Source : string.Empty;я вірю, що це ваша спроба досягти.


6
Мені це подобається. Оператор маршруту : він допомагає вам дістатися від А до В ... або від А до С ... залежно від А.
Рік Сладкі,

Так, він має на увазі тернар. Але правильна назва - "умовна".
Ерік Г. Хагстром


0

Я не думаю, що ви можете його оператором і припустити повернути той чи інший. Це не якщо заміна виписки else, хоча вона може бути використана для цього у певному випадку.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.