?: ?? Операторы вместо 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 (его метод доступа get).
John K
1
В вашем первом фрагменте кода есть геттер свойств, который вызывает собственный метод установки , который, в свою очередь, рекурсивно вызывает собственный метод получения . Вы потеряли меня там, потому что ничего подобного не может сработать в этой области. Уточните свой вопрос и объясните, чего именно вы хотите достичь.
Frédéric Hamidi
Ничего не вернуть? Это 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 01
4
Иногда вложенные тернарные операторы создают более читаемый код, если пробелы используются правильно.
правдивость 01
2
@truth: Да, я ничего не имею против вложенности ?:как таковой. Но у меня большая проблема с их использованием для потока управления, особенно вложенного потока управления!
Оливер Чарльзуорт
11

Ссылаясь на ?: Оператор (Справочник по C #)

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

Ссылаясь на ?? Оператор (Справочник по C #)

?? Оператор называется оператором объединения с нулевым значением и используется для определения значения по умолчанию для типов значений, допускающих значение NULL, а также для ссылочных типов. Он возвращает левый операнд, если он не равен нулю; в противном случае возвращается правильный операнд.

Это означает:

[Часть 1]

return source ?? String.Empty;

[Часть 2] не применяется ...

Акрам Шахда
источник
3
Это отличается от бездействия. Возвращает пустую строку.
правдивость 01
1
Конечно, но ОП просила не об этом. Я не виноват, что ОП попросил «ничего не вернуть» - что бы это ни значило.
правдивость 01
1
@trutheality: Никто не сказал, что это твоя вина .. Однако ОП не хотел ничего возвращать, и то, что я предоставил.
Akram Shahda
3

«Ничего не делать» действительно не работает?

если // Ничего не вернуть, вы на самом деле имеете в виду return null, тогда напишите

return Source;

если вы имеете в виду, игнорируйте кодовый путь, затем напишите

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

И напоследок

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

// nothing done.
Винник12
источник
3

Тернарный оператор ВОЗВРАЩАЕТ одно из двух значений. Или он может выполнить одно из двух операторов в зависимости от своего состояния, но это обычно не очень хорошая идея, поскольку может привести к непредвиденным побочным эффектам.

bar ? () : baz();

В этом случае () ничего не делает, а baz что-то делает. Но вы только сделали код менее понятным. Я бы выбрал более подробный код, более понятный и простой в обслуживании.

Кроме того, в этом нет никакого смысла:

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

Поскольку () не имеет типа возврата (он недействителен), а baz имеет тип возврата, который неизвестен в точке вызова в этом примере. Если они не согласны, компилятор громко пожалуется.

Майк Хофер
источник
2

Если вас беспокоит многословность вашего кода, я бы написал это, а не пытался злоупотреблять выражениями.

if (Source == value) return;
Source = value;
RaisePropertyChanged("Source");
ХаосПандион
источник
Я не злоупотребляю выражениями, я просто думаю!
Ахмед Гонейм
1

?: оператор маршрута. (полагаю, я правильно написал), и это просто в использовании. как в булевом предикате? iftrue: ifalse; Но у вас должно быть rvalue / lvalue, как в rvalue = predicate? iftrue: если ложно;

бывший int i = x < 7 ? x : 7;

если бы x было меньше 7, мне было бы назначено x, если бы не было 7.

вы также можете использовать его в качестве возврата, как в return x < 7 ? x : 7;

опять же, как и выше, это будет иметь тот же эффект.

Итак, Source = Source == value ? Source : string.Empty;я считаю, что это то, чего вы пытаетесь добиться.

Джонатан
источник
6
Мне это нравится. Маршрут Оператор : это поможет вам получить от А до Б ... или от А до С ... в зависимости от А.
Рик Слэдки
Да, он имеет в виду тройной. Но правильное название - «условное».
Erick G. Hagstrom
1

?:Оператор возвращает одно из двух значений в зависимости от значения логического выражения.

Condition-Expression ? Expression1 : Expression2

Подробнее об ?:операторе, также известном как тернарный оператор:

Руденаггар
источник
0

Я не думаю, что вы можете его оператор и предположить, что он вернет один или другой. Это не замена оператора if else, хотя его можно использовать для этого в определенных случаях.

atbebtg
источник