?のnull許容型の問題:条件演算子


154

これがC#.NET 2.0で機能する理由を誰かが説明できますか?

    Nullable<DateTime> foo;
    if (true)
        foo = null;
    else
        foo = new DateTime(0);

...しかし、これはしません:

    Nullable<DateTime> foo;
    foo = true ? null : new DateTime(0);

後者の形式では、「 '<null>'と 'System.DateTime'の間の暗黙的な変換がないため、条件式のタイプを判別できません。」というコンパイルエラーが発生します。

前者は使用できないというわけではありませんが、2番目のスタイルは他のコードとより一貫しています。


12
DateTimeを使用することで、入力の手間を省くことができますか?Nullable <DateTime>の代わりに。
スチュワートジョンソン

回答:


325

この質問はすでに何度も尋ねられています。コンパイラーはnull、に変換する方法がわからないことを通知していDateTimeます。

解決策は簡単です:

DateTime? foo;
foo = true ? (DateTime?)null : new DateTime(0);

Nullable<DateTime>書くことができるのでDateTime?、タイピングの手間が省けます。


十分に機能しますが、今ではfooをnullチェックすることはできません-常に値があります。ただし、これを回避する方法はありません。MojoFilterが言うように、「三項演算子では、2つの値が同じ型でなければならないからです。」
DilbertDave

@DilbertDave MojoFilterの投稿からの情報は正しくありません。
Mishax 2013

4
コンパイラーは、割り当てられた変数を調べるのではなく、代わりにオペランドを調べることによって、3項演算の結果の型を推測しようとすることを付け加えておきます。共通の祖先タイプを検出<null>DateTime、その代わりに、相互間の変換を検出しようとします。(追加ビット:C#は<null>タイプ、つまりすべてのnull式のタイプを認識します。)
IllidanS4はモニカに2014

既に何度も尋ねられた場合、重複する質問フラグはどこにありますか?
starmandeluxe

@starmandeluxe彼らはおそらくここを指しています(少なくとも私がここにたどり着いたのはそうです)
Scott Chamberlain

19

FYI(トピック外ですが、niftyでnull許容型に関連しています)には、null合体演算子と呼ばれるnull許容型専用の便利な演算子があります。

??

このように使用されます:

// Left hand is the nullable type, righthand is default if the type is null.
Nullable<DateTime> foo;
DateTime value = foo ?? new DateTime(0);

9
これは彼の質問にどのように答えますか?
スチュワートジョンソン

3
Nickは、ある条件が真の場合にnullをfooに割り当てようとしています。nullの合体は、fooがnullの場合、DateTime(0)を値に割り当てます。2つは完全に無関係です。
Jeromy Irvine、

4
したがって、参考までに、トピック外ですが、知っておきたいことです。
FlySwat 2008年

あ、そう。知っておくと便利です。
Jeromy Irvine、

8

これは、3項演算子では、2つの値が同じ型に解決される必要があるためです。


10
いいえ、同じタイプである必要はありません。2番目のオペランドは、3番目のオペランドの型に暗黙的に変換できるか、またはその逆でなければなりません。
Mishax 2013

3

この質問が2008年に行われたことは知っていますが、現在5年後ですが、回答としてマークされた回答は私を満足させません。本当の答えは、DateTimeは構造体であり、構造体としてはnullと互換性がないということです。それを解決するには2つの方法があります。

1つは、nullをDateTimeと互換性を持たせることです(たとえば、70の賛成票を持つ紳士が示唆するように、nullをDateTime?にキャストするか、nullをObjectまたはValueTypeにキャストします)。

2つ目は、DateTimeをnullと互換性を持つようにすることです(たとえば、DateTimeをDateTimeにキャストしますか?)。


3

受け入れられているのと同様の別の解決策は、C#のdefaultキーワードを使用することです。ジェネリックを使用して定義されていますが、実際にはどのタイプにも適用できます。

OPの質問に適用される使用例:

Nullable<DateTime> foo;
foo = true ? default(DateTime) : new DateTime(0);

現在受け入れられている回答の使用例:

DateTime? foo;
foo = true ? default(DateTime) : new DateTime(0);

また、を使用defaultすると、変数に値nullableを割り当てるために変数を指定する必要がなくなりnullます。コンパイラーは特定の変数タイプのデフォルト値を自動割り当てし、エラーは発生しません。例:

DateTime foo;
foo = true ? default(DateTime) : new DateTime(0);

13
真でdefault(DateTime)はなく、nullではなく、「1.1.0001 0:00:00」であり、と同じnew DateTime(0)です。
IllidanS4はモニカに2014

@ IllidanS4、私はそれがと等しいとは言いませんでした。それnullを使用default()することによってのみ、nullable値に割り当てることができます(MSDNによると)。例として、私はそれを一緒に使用することができ、汎用性を発揮示しNullable<DateTime>DateTime?と単純にDateTime。これが正しくないと思われる場合、これらが失敗するPoCを提供できますか?
newfurniturey 2018

3
さて、質問者はnullではなく変数に格納したかったdefault(DateTime)ので、これはせいぜい誤解を招くだけです。あなたは暗示として、全体としての表現はまだ同じ型を持っているので、これは、「万能」ではない- DateTime、あなたは置き換えることができdefault(DateTime)new DateTime()、それは同じことを行います。default(DateTime?)それは実際にはと等しいので、たぶんあなたが意図したことですnull
IllidanS4はモニカに2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.