web-dev-qa-db-ja.com

Nullable型と三項演算子:なぜ `? 10:null`は禁止されていますか?

私は奇妙なエラーに出会いました:

private bool GetBoolValue()
{
    //Do some logic and return true or false
}

次に、別の方法で次のようにします。

int? x = GetBoolValue() ? 10 : null;

メソッドがtrueを返す場合、Nullableint xに10を割り当てます。それ以外の場合は、-nullable intにnullを割り当てます。ただし、コンパイラは次のように文句を言います。

エラー1 int<null>の間に暗黙的な変換がないため、条件式のタイプを判別できません。

私は夢中になりますか?

240
BFree

コンパイラは最初に右辺式を評価しようとします:

GetBoolValue() ? 10 : null

10intリテラル(int?ではなく)であり、nullnullです。これら2つの間に暗黙的な変換はないため、エラーメッセージが表示されます。

右側の式を次のいずれかに変更すると、int?null(#1)およびintint?(#2、#3)の間に暗黙的な変換があるためコンパイルされます。 。

GetBoolValue() ? (int?)10 : null    // #1
GetBoolValue() ? 10 : (int?)null    // #2
GetBoolValue() ? 10 : default(int?) // #3
395
LukeH

これを試して:

int? x = GetBoolValue() ? 10 : (int?)null;

基本的に、条件演算子は式の「戻り値の型」を決定できないということです。コンパイラは10intであると暗黙的に決定するため、この式の戻り値の型もintであると決定します。 intnull(条件演算子の第3オペランド)にすることはできないため、文句を言います。

nullNullable<int>にキャストすることにより、この式の戻り値の型はNullable<int>であることをコンパイラーに明示的に伝えています。 10int?にキャストすることも簡単にでき、同じ効果があります。

34
Andrew Hare

これを試して:

int? result = condition ? 10 : default(int?);

15
Unknown

ちなみに、MicrosoftのC#コンパイラーの実装では、実際には非常に微妙で興味深い(私にとって)方法で条件演算子の型分析が間違っています。私の記事はタイプ推論の問題、パート1です。

14
Eric Lippert

次のいずれかを試してください。

int? x = GetBoolValue() ? (int?)10 : null;

int? x = GetBoolValue() ? 10 : (int?)null;
5
John Gietzen

問題は、三項演算子が最初のパラメーター割り当てに基づいて型を推測していることです...この場合、これはnull可能なintではなくintです。

あなたはもっと幸運があるかもしれません:

int? x = GetBoolValue() (int?)10 : null;
5
Justin Niessner

明示的なキャストを追加するだけです。

int? x = GetBoolValue() ? 10 : (int?)null;

混乱するのは3項演算子です-2番目の引数は整数であるため、3番目の引数も整数であると見なされ、nullは適合しません。

4

これは、コンパイラが条件演算子のタイプを、結果の割り当て先ではなく、第2および第3オペランドで決定するためです。コンパイラが型を決定するために使用できる整数とnull参照の間に直接キャストはありません。

4
Guffa
int? x = GetBoolValue() ? 10 : (int?)null;

これが表示される理由は、バックグラウンドでNullableを使用しており、「null」がNullableのnullインスタンスであることをC#に伝える必要があるためです。

4
Martin Peck