Есть ли "обратное" к нуль коалесцирующий оператора? (...на любом языке?)
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); но если у вас есть что-нибудь получше, я бы тоже хотел это увидеть.)
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иNothingNothing >> Just 1- этоNothingJust 2 >> NothingиNothingJust 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
Comments