ヌル合体演算子の「反対」はありますか?(…任意の言語で?)


92

nullの合体は、おおよそ 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);ますが、もっと良いものがあれば、それも見たいと思います。)


C#でx?.yのようなものを要求する人もいますが、そのようなものは存在しません。
Anthony Pegram

1
@アンソニーああ、それは美しいでしょう。ありがとう。
ジェイ

2
c ++では、それはとして表現するのに十分簡単return x ? x.y : NULLです。ポインタ型をブール値に変換してください!
Phil Miller、

1
@Novelocratは、C#で私をいらいらさせるものの1つです。if(0、false、null)の場合を除いて、if(anything)= trueの場合、Cに従っていませんでした
Chris Marisic

2
@Chris:Cに関する正確なステートメントではありません。非スカラー変数(構造体など)がある場合、それを条件で使用することはできません。
Phil Miller、

回答:


62

あります、nullで安全な間接参照演算子は(?)Groovyで...私はあなたが後にしているものと思います。

(これは、セーフナビゲーションオペレーターとも呼ばれます。)

例えば:

homePostcode = person?.homeAddress?.postcode

これはpersonperson.homeAddressまたはnullの場合にperson.homeAddress.postcodenullを返します。

(これは現在、C#6.0で使用できますが、以前のバージョン使用できません)


1
Groovyには "Elvis演算子"もあり、これにより、以外のデフォルト値を使用できますnull。例:def bar = foo ?: "<null>"
Craig Stuntz

28
この機能をC#5.0に推薦します。Groovyが実際に何であるかはわかりませんが、これはどの言語でも使用できるほど直感的です。
ジェルジAndrasek

ただし、C#6に追加される予定です。
Jeff Mercado 2015年

1
セーフナビゲーションは投稿された簡単な例で機能しますが、関数呼び出しでnull以外の値を使用する場合は、たとえば、次のように3項演算子を使用する必要がありますDecimal? post = pre == null ? null : SomeMethod( pre );。"Decimal?post = pre :: SomeMethod(pre);"まで減らすことができればすばらしいと思います。

@Dai:必要な順列の数を考えると、私たちが得たもので十分満足しています。
Jon Skeet、2016

36

?を追加することを検討しました。C#4へ。それはカットをしませんでした。これは「持っているのがいい」機能であり、「持っている」機能ではありません。この言語の将来の仮想バージョンについてもう一度考えますが、私があなただったら、私は息を止めません。時間が経つにつれ、それ以上重要になることはないでしょう。:-)


機能の実装の容易さは、機能を追加する決定に影響しますか?この演算子を実装するのは、かなり単純明快で、言語に追加するだけのように思えるためです。私はエキスパートではないので(C#が大好きな最近の卒業生)、修正してください!
Nick Strupat、2011年

14
@nick:確かに、レクサーとパーサーの実装は5分の作業です。次に、「IntelliSenseエンジンはそれをうまく処理できますか?」のようなことについて心配し始めます。また、「?を入力したが、。を入力しなかった場合、エラー回復システムはそれをどのように処理しますか?」そして、どれほど多くの異なることが「。」を行うのか。とにかくC#で意味し、それらのうちいくつが?その前に、エラーが発生した場合のエラーメッセージと、この機能に必要なテストの量(ヒント:たくさん)。そして、それをどのように文書化し、変更を伝えるか、そして...
Eric Lippert、2011年

3
@nick:質問に答えるために-はい、実装コストは要素ですが、小さなものです。私たちが働いているレベルでは安価な機能はなく、多かれ少なかれ高価な機能しかありません。パーサーを正しいコードのケースで機能させるための5ドル相当の開発作業は、数万ドル相当の設計、実装、テスト、文書化、および教育に簡単に変えることができます。
Eric Lippert、2011年

11
@EricLippertこれは、C#を非常に成功させ、コードを可能な限り簡潔で表現力豊かにするという使命に完全に貢献する、メジャーな「持っている」の1つになると思います。
Konstantin

:私はこれが追加見てみたい、私が本当にしたいことはエルビス演算子あるstackoverflow.com/questions/2929836/...
クリスMarisic

16

特別な種類の短絡ブールロジックがある場合は、これを実行できます(JavaScriptの例)。

return x && x.y;

xがnullの場合、は評価されませんx.y


2
ただし、これは0、 ""、およびNaNで短絡するため、??の反対ではありません。||の逆です。
ritaj

7

これを答えとして追加するのは正しいと感じました。

C#にそのようなものが存在しない理由は、合体演算子(参照型に対してのみ有効)とは異なり、逆の操作が参照型または値型(つまりclass x、メンバーを使用)を生成する可能性があるint yためです。多くの状況では使用できません。

しかし、私はそれを見たくないと言っているのではありません!

その問題の潜在的な解決策は、演算子が右側の値型式をnull可能に自動的に持ち上げることです。しかし、そのx.y場合、yがintである場合、実際にはanが返されるint?という問題があります。

別の、おそらくより良い解決策は、左側の式がnullの場合に、演算子が右側の型のデフォルト値(つまりnullまたはゼロ)を返すことです。しかし、ゼロ/ヌルが実際に読み取られたシナリオや、x.yそれがセーフアクセスオペレーターによって提供されたかどうかを区別する問題があります。


私が最初にOPの質問を読んだとき、この正確な問題が頭に浮かびましたが、それを明確に表現する方法を見つけることができませんでした。非常に深刻な問題です。+1
rmeador 2010年

深刻な問題ではありません。int?デフォルトの戻り値として使用するだけで、ユーザーは必要に応じてそれをintに変更できます。たとえばLookup、参照の1つが次の場合に、デフォルト値を-1にしていくつかのメソッドを呼び出したい場合nullfoo?.Bar?.Lookup(baz) ?? -1
Qwertie

方法有する約?. :右側の中間に所定の適切なメンバーと同じタイプであることが要求される三項演算子とすること?
スーパーキャット2013年

6

Delphiには(。ではなく):演算子があり、nullセーフです。

彼らは?を追加することを考えていました。演算子をC#4.0に変換して同じことを行いますが、チョッピングブロックを取得しました。

その間、かゆみを掻くようなIfNotNull()があります。確かに?または:でも、メンバーの1つがnullの場合にNullReferenceExceptionを発生させない一連の操作を作成できます。


この演算子の使用例を教えていただけますか?
Max Carroll

1
これ?.はC#6.0言語機能であり、はい、OPがここで要求したとおりに機能します。決して遅くないより良い^^
T_D

3

Haskellでは、次の>>演算子を使用できます。

  • Nothing >> Nothing です Nothing
  • Nothing >> Just 1 です Nothing
  • Just 2 >> Nothing です Nothing
  • Just 2 >> Just 1 です Just 1

3

Haskellにはfmapがあり、この場合はと同等だと思いますData.Maybe.map。Haskellは純粋に機能するので、探しているのは

fmap select_y x

場合がxありNothing、これを返しますNothing。場合がxありJust object、これを返しますJust (select_y object)。ドット表記ほどきれいではありませんが、関数型言語であることを考えると、スタイルは異なります。


2

PowerShellを使用すると、null参照でプロパティを参照できます(メソッドを呼び出すことはできません)。インスタンスが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
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"

1

メンバーのすべての正しいデフォルト値を使用して、クラスの静的インスタンスをどこかに作成します。

例えば:

z = new Thingy { y=null };

次にあなたの代わりに

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

あなたは書ける

return (x ?? z).y;

私はその手法を使用することもあります(例(x ?? "").ToString())が、PODや文字列などのいくつかのデータ型でのみ実用的です。
Qwertie

1

これはC#vNext(Roslyn搭載の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


1

いわゆる「ヌル条件演算子」は、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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.