Существует ли “противоположное” к пустому оператору объединения? (… на каком-либо языке?)

пустое объединение переводит примерно в 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);, но если бы у Вас есть что-нибудь лучше, я хотел бы видеть это также.)

87
задан Jay 28 May 2010 в 14:24
поделиться

8 ответов

В Groovy есть null-safe dereferencing operator (?.)... Я думаю, это то, что вам нужно.

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

Например:

homePostcode = person?.homeAddress?.postcode

Это даст null, если person, person.homeAddress или person.homeAddress.postcode равны null.

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

61
ответ дан 24 November 2019 в 07:50
поделиться

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

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

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

6
ответ дан 24 November 2019 в 07:50
поделиться

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

return x && x.y;

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

16
ответ дан 24 November 2019 в 07:50
поделиться

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

fmap select_y x

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

3
ответ дан 24 November 2019 в 07:50
поделиться

Просто захотелось добавить это в качестве ответа.

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

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

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

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

7
ответ дан 24 November 2019 в 07:50
поделиться

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

35
ответ дан 24 November 2019 в 07:50
поделиться

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

  • Nothing >> Nothing is Nothing
  • Nothing >> Just 1 is Nothing
  • Just 2 >> Nothing is Nothing
  • Just 2 >> Just 1 is Just 1
3
ответ дан 24 November 2019 в 07:50
поделиться

PowerShell позволяет ссылаться на свойства (но не вызывать методы) по пустой ссылке, и она вернет null, если экземпляр имеет значение NULL. Сделать это можно на любой глубине. Я надеялся, что динамическая функция 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);
2
ответ дан 24 November 2019 в 07:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: