Есть ли "обратное" к нуль коалесцирующий оператора? (...на любом языке?)



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

595   12  

12 ответов:

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

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

например:

homePostcode = person?.homeAddress?.postcode

это даст null, если person,person.homeAddress или person.homeAddress.postcode имеет значение null.

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

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

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

return x && x.y;

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

Он просто чувствовал себя хорошо, чтобы добавить это в качестве ответа.

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

Я не говорю, что я не хочу видеть его!

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

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

Delphi имеет: (вместо . оператор), который является null-безопасный.

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

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

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

  • Nothing >> Nothing и Nothing
  • Nothing >> Just 1 - это Nothing
  • Just 2 >> Nothing и Nothing
  • Just 2 >> Just 1 и Just 1

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

fmap select_y x

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

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);

создать статический экземпляр класса где-то с правильными значениями по умолчанию для членов.

например:

z = new Thingy { y=null };

затем вместо

return x != null ? x.y : null;

можно писать

return (x ?? z).y;
public class ok<T> {
    T s;
    public static implicit operator ok<T>(T s) { return new ok<T> { s = s }; }
    public static implicit operator T(ok<T> _) { return _.s; }

    public static bool operator true(ok<T> _) { return _.s != null; }
    public static bool operator false(ok<T> _) { return _.s == null; }
    public static ok<T> operator &(ok<T> x, ok<T> y) { return y; }
}

мне часто нужна эта логика для строк:

using ok = ok<string>;

...

string bob = null;
string joe = "joe";

string name = (ok)bob && bob.ToUpper();   // name == null, no error thrown
string boss = (ok)joe && joe.ToUpper();   // boss == "JOE"

Это добавляется в C# vNext (Roslyn powered C#, выпуски с 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

так называемый "оператор null-conditional" был введен в C# 6.0 и в Visual Basic 14.
Во многих ситуациях он может быть использован как полная противоположность оператору null-coalescing:

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

Comments

    Ничего не найдено.