Тернарный условный оператор для левого операнда в C# - PullRequest
1 голос
/ 02 мая 2020

Можно ли выбрать переменную назначения на основе некоторого встроенного условия без оператора if?

(!RTL ? padLeft : padRight) = NearBorder.LineWidth;

Ответы [ 4 ]

1 голос
/ 02 мая 2020

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

    var a = new Action<int>( i => padLeft = i );
    var b = new Action<int>( i => padRight = i );

    (!RTL ? a : b)(NearBorder.LineWidth);
0 голосов
/ 02 мая 2020

Если вы используете достаточно новую версию C# (7.2+), и эти переменные являются локальными или полевыми, то вы можете использовать ref locals;

(!RTL ? ref padLeft : ref padRight) = NearBorder.LineWidth;

См. sharplab ссылка для примера. Обратите внимание, что предложение документов (которые обозначают это как conditional ref) указывают, что это все еще предложение. Проблема Championed GitHub по-прежнему открыта , но, похоже, указывает на то, что единственное, чего не хватает, - это истинной спецификации. Этот комментарий по этому вопросу предполагает, что все это было реализовано как часть большой темы ref readonly.

Кроме этого, этот код работает для меня как в SharpLab, так и локально в VS2019 (последний, без предварительного просмотра, с использованием do tnet core 3.0)

Если эти переменные были полями, вы может также использовать ref return и инкапсулировать logi c в функцию. Например:

// class fields
int padLeft, padRight;  
// ref returning method 
private ref int GetPad() => ref (!RTL ? ref padLeft : ref padRight);
// actually use it
void SetPad() {
    // assignment to a method! 
    GetPad() = NearBorder.LineWidth;
} 

Для получения дополнительной информации о концепции ref locals и ref returns (первоначально являющейся частью C# 7), см. Эту статью MSDN .

0 голосов
/ 02 мая 2020

Нет, это невозможно. Из спецификации C# :

Левый операнд присваивания должен быть выражением, классифицированным как переменная, доступ к свойству, доступ к индексатору или доступ к событию.

Таким образом, левая часть оператора = может быть только одной из следующих:

  • Переменная (var variable_name = expression)
  • Доступ к свойству (someObject.someProperty = expression)
  • Доступ к индексатору (someObject[anIndex] = expression)

(«Доступ к событию» более ограничен и может использоваться только с операторами += и -=, а не с простым оператором =.)

Лучшее, что вы можете сделать, это оператор if.

if (!RTL)
{
    padLeft = NearBorder.LineWidth;
}
else
{
    padRight = NearBorder.LineWidth;
}
0 голосов
/ 02 мая 2020

Давайте попробуем и посмотрим, что произойдет:

var a =1; var b =1; var c=1;
(a == 1? b : c) = 4

если вы запустите это, вы получите

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

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

!RTL ? padLeft = NearBorder.LineWidth : padRight = NearBorder.LineWidth;

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

padLeft = RTL ? NearBorder.LineWidth: 0;
padRight = !RTL ? NearBorder.LineWidth: 0;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...