Есть ли "противоположность" оператору слияния? (... на любом языке?) - PullRequest
86 голосов
/ 28 мая 2010

объединение нуля переводится примерно в return x, unless it is null, in which case return y

Мне часто нужно return null if x is null, otherwise return x.y

Я могу использовать return x == null ? null : x.y;

Неплохо, но то, что null в середине, всегда беспокоит меня - это кажется излишним. Я бы предпочел что-то вроде return x :: x.y;, где то, что следует за ::, оценивается, только если то, что предшествует ему, не null.

Я вижу это как почти , противоположное нулевой коалесценции, вроде смешанного с краткой, встроенной нулевой проверкой, но я [ почти ] уверен, что такого оператора нет в C #.

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

(я знаю, что могу написать метод для этого на C #; я использую return NullOrValue.of(x, () => x.y);, но если у вас есть что-то лучше, я бы тоже хотел это увидеть.)

Ответы [ 12 ]

61 голосов
/ 28 мая 2010

В Groovy есть нулевой безопасный оператор разыменования (?.) ... Я думаю, это то, что вам нужно.

(также называется оператор безопасной навигации .)

Например:

homePostcode = person?.homeAddress?.postcode

Это даст ноль, если person, person.homeAddress или person.homeAddress.postcode равно нулю.

(теперь это доступно в C # 6.0 , но не в более ранних версиях)

34 голосов
/ 29 мая 2010

мы рассматривали добавление? на C # 4. Это не сделать разрез; это функция «приятно иметь», а не «надо иметь». Мы рассмотрим это снова для гипотетических будущих версий языка, но я бы не стал затаить дыхание, ожидая тебя. С течением времени это вряд ли станет более важным. : -)

16 голосов
/ 28 мая 2010

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

return x && x.y;

Если x равно нулю, оно не будет оцениваться x.y.

7 голосов
/ 28 мая 2010

Было бы правильным добавить это в качестве ответа.

Я думаю, причина того, почему в C # такого нет, заключается в том, что в отличие от оператора объединения (который действителен только для ссылочных типов),обратная операция может привести либо к ссылке, либо к типу значения (т. е. class x с элементом int y - поэтому, к сожалению, это будет невозможно использовать во многих ситуациях.

Однако я не говорю, что не будухотел бы видеть это!

Потенциальное решение этой проблемы могло бы для оператора автоматически поднять выражение типа значения с правой стороны до нуля. Но тогда возникает проблема, которая x.y, гдеy - это int, которое на самом деле вернет int?, что было бы неприятно.

Другое, возможно, лучшее решение для оператора - вернуть значение по умолчанию (т. е. ноль или ноль) для типа нас правой стороны, если выражение слева равно нулю. Но тогда у вас есть проблемы, отличающие сценарии, где нулевой / нулевой был фактически прочитан из x.y или гдетакже он был предоставлен оператором безопасного доступа.

6 голосов
/ 28 мая 2010

Delphi имеет оператор: (вместо.), Который является нулевым.

Они думали о добавлении? Оператор C # 4.0, чтобы сделать то же самое, но это получил рубящий блок.

В то же время, есть IfNotNull () , какой вид царапин, которые зудят. Это конечно больше чем? или:, но он позволяет вам составить цепочку операций, которые не будут создавать исключение NullReferenceException, если один из членов имеет значение null.

3 голосов
/ 28 мая 2010

Haskell имеет fmap, что в данном случае, я думаю, эквивалентно Data.Maybe.map. Haskell является чисто функциональным, поэтому то, что вы ищете, будет

fmap select_y x

Если x равно Nothing, возвращается Nothing. Если x равно Just object, возвращается Just (select_y object). Не так красиво, как точечная нотация, но, учитывая, что это функциональный язык, стили разные.

3 голосов
/ 28 мая 2010

В Haskell вы можете использовать оператор >>:

  • Nothing >> Nothing является Nothing
  • Nothing >> Just 1 - это Nothing
  • Just 2 >> Nothing является Nothing
  • Just 2 >> Just 1 является Just 1
2 голосов
/ 28 мая 2010

PowerShell позволяет вам ссылаться на свойства (но не вызывать методы) на нулевую ссылку, и он возвращает нуль, если экземпляр является нулевым. Вы можете сделать это на любой глубине. Я надеялся, что динамическая функция C # 4 поддержит это, но это не так.

$x = $null
$result = $x.y  # $result is null

$x = New-Object PSObject
$x | Add-Member NoteProperty y 'test'
$result = $x.y  # $result is 'test'

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

public static TResult SafeGet<T, TResult>(this T obj, Func<T, TResult> selector) {
    if (obj == null) { return default(TResult); }
    else { return selector(obj); }
}

var myClass = new MyClass();
var result = myClass.SafeGet(x=>x.SomeProp);
1 голос
/ 06 апреля 2018

Так называемый «нулевой условный оператор» был введен в C # 6.0 и в Visual Basic 14.
Во многих ситуациях это может быть использовано как полная противоположность нуль-коалесцирующему оператору:

int? length = customers?.Length; // null if customers is null   
Customer first = customers?[0];  // null if customers is null  
int? count = customers?[0]?.Orders?.Count();  // null if customers, the first customer, or Orders is null

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators

1 голос
/ 01 декабря 2014

Это добавляется в C # vNext (C # на базе Roslyn, выпускается с Visual Studio 2014).

Это называется нулевым распространением и указано здесь как завершенное. https://roslyn.codeplex.com/wikipage?title=Language%20Feature%20Status

Он также указан здесь как полный: https://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/3990187-add-operator-to-c

...