Подтвердить что ты не робот

Монадическая проверка нуля в С# 6.0

Я наткнулся на интересный сайт, на котором рассматриваются некоторые из новых (предлагаемых) возможностей С# 6.0. Вы можете прочитать его здесь: Вероятные функции С# 6.0.

То, что я нахожу особенно интересным, - это монадическая нулевая проверка (также известная как оператор NULL-распространения ?.). Согласно сайту, следующий оператор

var bestValue = points?.FirstOrDefault()?.X ?? -1;

содержит монадическую нулевую проверку, которая в настоящее время реализована с помощью этого фрагмента кода:

if (points != null) 
{
  var next = points.FirstOrDefault();
  if (next != null && next.X != null) return next.X;
}   
return -1;

Мой первый взгляд был, эй, что здесь написано? Но, посмотрев на "старый" код, мне начинает нравиться.

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

  • Я предполагаю, что этот оператор, распространяющий нуль, является потокобезопасным. Но как это происходит? Исчезнут ли условия гонки или они сохраняются?
  • Как этот оператор будет обрабатывать общие типы? Более того, как бы это касалось неограниченных родовых типов? Например, рассмотрим

    var resultAfterNullCheck = x?.Y;
    

    Если тип Y здесь создается с помощью ссылочных типов, типов с нулевыми значениями и типов значений с нулевым значением, не было бы ничего разумного (поскольку я не могу думать о том, что делать, поскольку я просто не знаю, что делать). Итак, есть ли дефолт, который будет возвращен? Или это вызовет ошибку?

  • При взгляде на пример, который предоставляет сайт (и который я скопировал выше), я предполагаю, что одним из основных преимуществ оператора null-распространения является то, что он будет оценивать оператор только один раз. Однако (возможно, из-за моего незнания CLR), мне очень любопытно, как это можно выполнить.
    Что касается меня, то первая оценка (если точки равны нулю) должна инициировать метод расширения FirstOrDefault() для запуска, когда точки не являются нулевыми, а затем оценка возвращаемого типа должна быть нулевой или нет, а если нет, то X будет вернулся. Значит, это три оценки в сочетании с одной? Или я понимаю это неправильно? Это повлияет на скорость выполнения?

Другими словами, что будет быстрее, старый способ выполнения нулевых проверок или этот новый прекрасный оператор? Я попытаюсь изучить это, выполнив некоторые исследования, как только будет завершена загрузка Visual Studio 2015... Но для этого требуется немного терпения...

Есть ли мысли по этому новому типу оператора? Это действительно все еще предложенный вариант, или мы действительно можем рассчитывать на работу с этой новой монадической нулевой проверкой?

ИЗМЕНИТЬ
Поскольку Мэтью Уотсон предоставил приятную статью MSDN, обсудив эту (и более) тему, мне было любопытно, если бы он упомянул мой предыдущий вопрос о неограниченных дженериках и как этот оператор справляется с этим. К сожалению, я еще не нашел ответа. Хотя я буду предполагать, что программист должен попытаться предотвратить использование неконституционных дженериков, я все же могу предположить, что это иногда невозможно. Если это так, будет ли действительно необходима редизайн?

4b9b3361

Ответ 1

Ты переусердствуешь. Один за другим, ваши вопросы:

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

  • Если ваш общий тип допускает нулевое сравнение (что будет использовать этот оператор за кулисами), тогда код будет испускаться. Если нет, вы получите ошибку компиляции (например, если вам нужен тип типа значения). Это касается всех случаев!

  • Он вызывается один раз для каждого оператора, как обычный оператор .. Если вы скажете A.b.c, это все равно будет два уровня косвенности, и использование этого нового оператора ничего не изменит, оно просто проверяет и на нули.

Реальные преимущества ?. заключаются в том, что он является семантическим (вы можете сразу понять, что делает ваш код) и короткое замыкание (делает код намного короче вложенных if s). Вы не собираетесь заменять каждый . в своем старом коде на ?., на самом деле вы, вероятно, редко его используете. Но есть случаи, когда это будет полезно, например, в выражениях Linq, следующих за операциями ...OrDefault() или вызывающих событиях.

Ответ 2

Чтобы частично ответить на ваш первый вопрос, согласно John Skeet в своем блоге, нулевой оператор условного оператора ?. (= оператор распространения null) является потокобезопасным.

Ответ 3

Вы можете найти все о планируемых функциях в обсуждении проекта Roslyn. Вы также можете попробовать новые функции с консольным приложением, используя Roslyn, как nuget-package (это означает, что он работает с Visual Studio 2013 <)