zerowa koalescencja przekłada się z grubsza na return x, unless it is null, in which case return y
Często potrzebuję return null if x is null, otherwise return x.y
mogę użyć return x == null ? null : x.y;
Nieźle, ale to null
w środku zawsze mi przeszkadza - wydaje się zbędne. Wolałbym coś takiego return x :: x.y;
, w którym to, co następuje po tym, ::
jest oceniane tylko wtedy, gdy to, co go poprzedza, nie jest null
.
Widzę to jako prawie przeciwieństwo koalescencji zerowej, w pewnym sensie zmieszane ze zwięzłym, wbudowanym sprawdzaniem null, ale jestem [ prawie ] pewien, że nie ma takiego operatora w C #.
Czy są inne języki, które mają takiego operatora? Jeśli tak, jak to się nazywa?
(Wiem, że mogę napisać odpowiednią metodę w C #; używam return NullOrValue.of(x, () => x.y);
, ale jeśli masz coś lepszego, też chciałbym to zobaczyć).
return x ? x.y : NULL
. Hej za konwersję typów wskaźników na wartości logiczne!Odpowiedzi:
W Groovy jest operator dereferencji bezpieczny zerowo (?.) ... Myślę, że właśnie tego szukasz.
(Nazywa się to również operatorem bezpiecznej nawigacji ).
Na przykład:
To da null, jeśli
person
,person.homeAddress
lubperson.homeAddress.postcode
jest null.(Jest to teraz dostępne w C # 6.0, ale nie we wcześniejszych wersjach)
źródło
null
np .:def bar = foo ?: "<null>"
Decimal? post = pre == null ? null : SomeMethod( pre );
. Byłoby miło, gdybym mógł zredukować to do „Decimal? Post = pre :: SomeMethod (pre);”Rozważaliśmy dodanie? do C # 4. Nie udało się; jest to funkcja „miło mieć”, a nie funkcja „trzeba mieć”. Rozważymy to ponownie w przypadku hipotetycznych przyszłych wersji języka, ale nie wstrzymywałbym oddechu, czekając, gdybym był tobą. W miarę upływu czasu prawdopodobnie nie stanie się to bardziej istotne. :-)
źródło
Jeśli masz specjalną logikę logiki zwarciowej, możesz to zrobić (przykład javascript):
return x && x.y;
Jeśli
x
jest null, nie zostanie oszacowanyx.y
.źródło
Po prostu wydawało się właściwe, aby dodać to jako odpowiedź.
Wydaje mi się, że powodem, dla którego nie ma czegoś takiego w C #, jest to, że w przeciwieństwie do operatora koalescencji (który jest ważny tylko dla typów referencyjnych), operacja odwrotna może dać typ referencyjny lub wartość (tj.
class x
Z elementem członkowskimint y
- dlatego niestety byłoby bezużyteczne w wielu sytuacjach.Nie mówię jednak, że nie chciałbym tego oglądać!
Potencjalne rozwiązanie tego problemu spowodowałoby, że operator automatycznie podniósłby wyrażenie typu wartości po prawej stronie do wartości null. Ale wtedy
x.y
pojawia się problem polegający na tym, że gdy y jest liczbą int, w rzeczywistości zwróci to,int?
co byłoby uciążliwe.Innym, prawdopodobnie lepszym rozwiązaniem byłoby zwrócenie przez operatora wartości domyślnej (tj. Null lub zero) dla typu po prawej stronie, jeśli wyrażenie po lewej stronie ma wartość null. Ale wtedy masz problemy z rozróżnieniem scenariuszy, w których faktycznie odczytano zero / null
x.y
lub czy został on dostarczony przez operatora bezpiecznego dostępu.źródło
int?
jako domyślnej wartości zwracanej, a użytkownik może zmienić ją na int, jeśli chce. Na przykład, jeśli chciałbym wywołać jakąś metodęLookup
z domyślną wartością -1 w przypadku, gdy jedną z moich referencji jestnull
:foo?.Bar?.Lookup(baz) ?? -1
?. :
operatorem trójskładnikowym, w którym prawa strona musi być tego samego typu, co odpowiedni element członkowski podany w środku?Delphi ma operator: (zamiast.), Który jest bezpieczny dla wartości null.
Myśleli o dodaniu? operator do C # 4.0, aby zrobić to samo, ale to dostało blok do krojenia.
W międzyczasie istnieje IfNotNull (), który rodzaj zadrapań, które swędzi. Z pewnością jest większy niż? lub:, ale pozwala ci skomponować łańcuch operacji, który nie będzie miał wyjątku NullReferenceException, jeśli jeden z elementów członkowskich jest pusty.
źródło
?.
to funkcja języka C # 6.0 i tak, robi dokładnie to, o co poprosił tutaj OP. Lepiej późno niż wcale ^^W Haskell możesz użyć
>>
operatora:Nothing >> Nothing
jestNothing
Nothing >> Just 1
jestNothing
Just 2 >> Nothing
jestNothing
Just 2 >> Just 1
jestJust 1
źródło
Haskell tak zrobił
fmap
, co w tym przypadku wydaje mi się równoważneData.Maybe.map
. Haskell jest czysto funkcjonalny, więc to, czego szukasz, byłobyJeśli
x
takNothing
, to zwracaNothing
. Jeślix
takJust object
, to zwracaJust (select_y object)
. Nie tak ładne jak notacja kropkowa, ale biorąc pod uwagę, że jest to język funkcjonalny, style są różne.źródło
PowerShell pozwala odwoływać się do właściwości (ale nie wywoływać metod) w odwołaniu o wartości null i zwróci wartość null, jeśli wystąpienie ma wartość null. Możesz to zrobić na dowolnej głębokości. Miałem nadzieję, że dynamiczna funkcja C # 4 będzie to obsługiwać, ale tak nie jest.
$x = $null $result = $x.y # $result is null $x = New-Object PSObject $x | Add-Member NoteProperty y 'test' $result = $x.y # $result is 'test'
To nie jest ładne, ale możesz dodać metodę rozszerzenia, która będzie działać tak, jak opisujesz.
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);
źródło
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; } }
Często potrzebuję tej logiki dla ciągów:
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"
źródło
Utwórz gdzieś statyczną instancję swojej klasy ze wszystkimi właściwymi wartościami domyślnymi dla członków.
Na przykład:
z = new Thingy { y=null };
to zamiast twojego
return x != null ? x.y : null;
Możesz pisać
return (x ?? z).y;
źródło
To jest dodawane w C # vNext (język C # oparty na Roslyn, wydania z Visual Studio 2014).
Nazywa się to propagacją zerową i jest tutaj wymienione jako kompletne. https://roslyn.codeplex.com/wikipage?title=Language%20Feature%20Status
Jest tutaj również wymieniony jako kompletny: https://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/3990187-add-operator-to-c
źródło
Tak zwany „operator warunkowy zerowy” został wprowadzony w C # 6.0 i Visual Basic 14.
W wielu sytuacjach może być używany jako dokładne przeciwieństwo operatora koalescencji zerowej:
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
źródło