Вызов метода с использованием тернарного оператора - PullRequest
40 голосов
/ 30 марта 2011

Играя с новыми концепциями, я наткнулся на Ternary Operator и это красота.Поработав с ним некоторое время, я решил проверить его ограничения.

Однако мое веселье быстро закончилось, когда я не смог получить определенную строку кода для компиляции.

int a = 5;
int b = 10;
a == b ? doThis() : doThat() 

    private void doThis()
    {
        MessageBox.Show("Did this");
    }
    private void doThat()
    {
        MessageBox.Show("Did that");
    }

Эта строка дает мне две ошибки:

Error   1   Only assignment, call, increment, decrement, and new object expressions can be used as a statement
Error   2   Type of conditional expression cannot be determined because there is no implicit conversion between 'void' and 'void'

Я никогда не использовал Ternary Operator, чтобы решить, какой метод вызывать, и при этом я не знаю, возможно ли это вообще.Мне просто нравится идея однострочного If Else Statement для вызова метода.

Я провел небольшое исследование и не могу найти никаких примеров того, как кто-то делает это, поэтому я думаю, что я могу надеяться на что-тоэто не может обеспечить.

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

Ответы [ 7 ]

38 голосов
/ 30 марта 2011

троичный оператор используется для возврата значений, и эти значения должны быть назначены. Предполагая, что методы doThis() и doThat() возвращают значения, простое назначение решит вашу проблему.

Если вы хотите сделать то, что вы пытаетесь, это возможно, но решение не изящное.

int a = 5;
int b = 10;
(a == b ? (Action)doThis : doThat)();

Возвращает делегат Action, который затем вызывается в круглых скобках. Это не типичный способ достижения этого.

18 голосов
/ 30 марта 2011

Тернарный оператор должен что-то вернуть. Типичное использование выглядит так:

int x = (a > b) ? a : b;

Если вы попробуете что-то вроде

a + b;

Компилятор будет жаловаться.

(a > b) ? a - b : b - a;

- это, по сути, сокращение для «a - b» или «b - a», которые сами по себе не являются допустимыми утверждениями.

8 голосов
/ 30 марта 2011

Если вы действительно хотите вызывать void методы в условном операторе, вы можете использовать делегаты:

(something ? new Action(DoThis) : DoThat)();

Если методы принимают параметры, это станет более сложным.
Вы можете либопоместите лямбда-выражения в условные выражения или используйте Action<T>.

Однако это очень глупая вещь.

3 голосов
/ 30 марта 2011

Причина, по которой вышеприведенное утверждение не работает, была предоставлена ​​другими пользователями и фактически не ответила на мой настоящий вопрос.

Поиграв еще немного, я понял, что вы МОЖЕТЕ использовать этот оператор для выполненияприведенное выше утверждение, но оно приводит к некоторому плохому коду.

Если бы я изменил приведенное выше выражение на;

int a = 5;
int b = 10;
int result = a == b ? doThis() : doThat(); 

private int doThis()
{
    MessageBox.Show("Did this");
    return 0;
}
private int doThat()
{
    MessageBox.Show("Did that");
    return 1;
}

Этот код будет компилироваться и выполняться так, как должен.Однако, если эти методы изначально не предназначались для возврата чего-либо и ссылались на другие области в коде, теперь вам придется каждый раз обрабатывать возвращаемый объект для вызова этих методов.

В противном случае вы теперь можете использовать троичнуюоператор для однострочного метода выбора и даже знать, какой метод он вызвал в следующей строке, используя результат.

int result = a == b ? doThis() : doThat();

if (result == 0)
   MessageBox.Show("You called doThis()!");

Теперь этот код абсолютно бессмыслен и может быть легко выполнен If Else, ноЯ просто хотел знать, можно ли это сделать, и что нужно было сделать, чтобы заставить его работать.

Теперь, когда я знаю, что вы можете эффективно возвращать любой тип в этих методах, это может стать немного болееполезно.Это может считаться «Плохой практикой кодирования», но может стать очень полезным в ситуациях, для которых никогда не было СООТВЕТСТВУЮЩЕГО.

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

UserPrivileges result = user.Group == Group.Admin ? GiveAdminPrivileges() : GiveUserPrivileges();

private UserPrivileges GiveAdminPrivileges()
{
      //Enter code here
      return var;
}
private UserPrivileges GiveUserPrivileges()
{
      //Enter code here
      return var;
}

Конечно, это можно сделать с помощью оператора If, но я думаю, что использование тернарного оператора для других целей делает программирование увлекательным.Теперь это может быть не так эффективно, как утверждение If Else, в этом случае я бы никогда не использовал это.

3 голосов
/ 30 марта 2011

Вы должны быть в состоянии сделать это, хотя:

        int a = 5;
        int b = 10;

        var func = a == b ? (Action)doThis : (Action)doThat; // decide which method

        func(); // call it

Не то, чтобы это действительно так полезно.

2 голосов
/ 30 марта 2011

Условный оператор - это выражение, которое возвращает значение.
Его нельзя использовать с функциями, которые возвращают void.

Вместо этого следует использовать обычный if.

1 голос
/ 30 марта 2011

.NET не (легко) не поддерживает (читаемую версию) это по причине.Это очень неудобно и делает ваш код трудным для чтения.Логические деревья должны быть относительно легко пройти.Если бы я пришел к работе и ко всему коду, который они использовали, использовал троичный код для присвоения значений, вызова методов и т. Д. Я думаю, я бы просто ушел.

...