Почему я не могу сделать ?? = в C #? - PullRequest
16 голосов
/ 17 февраля 2009

Я часто ловлю себя на том, что делаю:

foo = foo ?? x;

Почему я не могу сделать:

foo ??= x;

Редактировать : Я знаю, что это не часть языка ... Мой вопрос "почему нет"? Я считаю необходимость повторять "foo" неприятной и потенциально подверженной ошибкам. Это выглядит так же безобразно, как:

foo = foo + x;

Ответы [ 13 ]

19 голосов
/ 17 февраля 2009

Когда я думаю об этом,

foo = foo ?? x 

на самом деле просто

foo = foo != null ? foo : x

и в этот момент аналогия + = начинает разваливаться.

14 голосов
/ 17 февраля 2009

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

Питер Халлам некоторое время был ведущим разработчиком компилятора C #, а также членом команды разработчиков языка C #. Он написал о своем способе измерения новой функции, названной Yardstick , хотя он был сосредоточен больше на функциях интерактивного графического интерфейса, чем на языковых.

Этот текст особенно актуален для вопроса ??=:

Часто правильное проектное решение заключается в ничего не менять. Это наверное самый важный урок, который я выучил от просмотра Андерса в C # языковой дизайн встреч. Часто область языка поднимается в который там кажется некоторым реальным выгоды, которые могут быть сделаны. Мы могли бы запретить пользователю общую кодировку ошибка, или мы могли бы улучшить удобство использования языка для определенного проблемный домен. Потом подумав очень тяжело, через все варианты решения проблемы, ответ сделать .... ничего! Четное хотя проблема действительна, и это похоже, мы должны быть в состоянии добавить что-то, чтобы улучшить ситуацию, после тщательного размышления нет способ решить проблему, которая делает не стоит больше, чем выигрывает решение. Многие из самых важных и ценные решения, которые я видел, Андерс принимать решения не добавлять сложность языка, если только Добавленная стоимость оправдывает сложность. В пограничных случаях он всего всегда ничего не выбирает над добавлением что-то маргинальное.

Ссылки:

14 голосов
/ 17 февраля 2009

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

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

9 голосов
/ 17 февраля 2009

?? не является «оператором» в том смысле, что он выполняет «операцию» со значением операндов. Вы должны рассматривать его как языковую конструкцию .

Предположим, у вас было:

node = node.next;

Хотели бы вы иметь возможность делать следующее?

node .= next;

Я думаю, что ??= не существует по той же причине, по которой .= не существует.

Кроме того, унарные операторы, такие как +=, *= и т. Д., Имеют прямые аналоги на уровне сборки. Псевдо-сборки:

add reg0, 1
mul reg1, 5

Это просто "естественно", что эти операторы существуют.

5 голосов
/ 17 февраля 2009

Существует гораздо более простой ответ, который каждый пропускает, обсуждая, имеет ли смысл аналогия от ??= до +=.

Вопрос: Почему вы не можете сделать foo ??= x; в C #?

Ответ: Поскольку каждая функция начинается с минус 100 баллов , функции начинаются с несуществующего, и кто-то должен заставить их произойти и, скорее всего, если они добавят эту функцию, ресурсы были потрачены на что-то, что принесло бы большую пользу клиентской базе :

... подумайте о времени и усилиях необходимо спроектировать, как функция должно работать, прибить все границы условия, а затем код написать автоматизированные тесты для этого, ... написать документация и справочный текст, а также продолжать поддерживать код, тесты, и документация для функции ожидаемая продолжительность жизни (которая в этом дело наверное навсегда). Мог все эти ресурсы были потрачены на то, что будет иметь большее общая выгода для клиентской базы? (Ответ на это всегда «Да» - все и ее невестка можно найти способ закончить предложение, «Я не могу поверить, что они потратили все это время на эту глупую функцию вместо крепление ... ")

5 голосов
/ 17 февраля 2009

Нет оператора, который выполняет эту операцию. Тем не менее, это интересное предложение для будущей версии языка. Я подозреваю, что он не был включен до сих пор, потому что основной вариант использования для оператора объединения, ??, имеет тип Nullable и получает значение как:

int? testValue;

return testValue ?? 0;

Вместо того, чтобы в операциях присваивания, как ваш пример. Кроме того, тогда как += гарантированно изменяет значение foo во всех случаях, но += 0, ??= не будет.

3 голосов
/ 13 июня 2018

Обновление 2017 : Нулевое слияние является активным предложением, которое находится на рассмотрении команды разработчиков языка C #. Пожалуйста, проголосуйте или присоединитесь к обсуждению на https://github.com/dotnet/csharplang/issues/34

3 голосов
/ 17 февраля 2009

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

Возможно, вы устанавливаете foo на основе некоторого значения базы данных, которое оказывается NULL, поэтому было бы более разумно использовать ?? оператор во время этого назначения (что устраняет необходимость в ?? =):

foo = (int?)rows["possiblyNullCount"] ?? 0;

вместо:

foo = (int?)rows["possiblyNullCount"];
foo = foo ?? 0;
2 голосов
/ 18 февраля 2009

Я тоже по ней скучаю - Руби погубила меня. Вот аналогичная конструкция, которую вы можете использовать в выражении (если у вас нет аллергии на побочные эффекты):

foo ?? foo = x;

как в:

return foo ?? foo = x;

или (только для иллюстрации!):

DoStuff( foo ?? foo = x );

Использование этого шаблона вне свойства get, вероятно, не очень хорошая идея.

2 голосов
/ 17 февраля 2009

Хотя это не совсем то, что вы просите (это не ?? =) ... Возможно, вы могли бы использовать методы расширения.

static void Main(string[] args)
{
    object foo = null;
    object x = "something";
    Console.WriteLine(foo.NullToValue(x));
}

public static class ObjectExtensions
{
    public static object NullToValue(this object obj, object value)
    {
        return obj != null ? obj : value;
    }
}

Я не тратил много времени на размышления о возможных способах, по которым это не сработает, но, похоже, он прошел тест на запах в моем примере приложения ...

...