13

単一の基本型から継承する 2 つの型で使用すると、条件演算子 ( ?:) が機能しないのはなぜですか?

私が持っている例は次のとおりです。

ActionResult foo = (someCondition)? 
                      RedirectToAction("Foo","Bar") :
                      Redirect(someUrl);

長い形式がうまく機能する場所:

ActionResult foo;

if(someCondition)
{
  foo = RedirectToAction("Foo","Bar");
}
else
{
  foo = Redirect(someUrl);
}

両方の戻り値の型RedirectToRouteResultRedirectResultは、 から継承しActionResultます。

4

3 に答える 3

17

単一の基本型から継承する 2 つの型で使用すると、条件演算子 (?:) が機能しないのはなぜですか?

条件式の型は、言語仕様に従って、2 番目のオペランドの型または 3 番目のオペランドの型のいずれかでなければなりません。コンパイラは、共通の基本型、または両方のオペランドを変換できる別の型を見つけようとしません。式を使用しても、その型が決定される方法には影響しません。したがって、ここでは変数の割り当ては関係ありません。

言語がこのように定義されている理由については、指定、実装、テスト、予測がかなり簡単になります。これは、言語設計ではかなり一般的です。言語を単純に保つことは、特定の状況で少し厄介になるとしても、通常、長期的にはより良い方法です。

詳細については、C# 4 仕様のセクション 7.14 を参照してください。

2 番目または 3 番目のオペランドを条件式に実際に必要な型にキャストすることが、問題を解決する方法です。これがよく発生する別の状況は、null 許容型であることに注意してください。

// Invalid
int? a = SomeCondition ? null : 10;

// All valid
int? a = SomeCondition ? (int?) null : 10;
int? b = SomeCondition ? default(int?) : 10;
int? c = SomeCondition ? null : (int?) 10;
于 2012-06-09T19:49:53.110 に答える
1

条件演算子は、そのコンポーネントから結果の型を判別できません。これは または のいずれRedirectToRouteResultRedirectResultです。これを解決するには、コンポーネントのいずれか (または両方) を基本型に明示的にキャストする必要があります。

ActionResult foo = (someCondition) ? 
                   (ActionResult)RedirectToAction("Foo","Bar") :
                   Redirect(someUrl);
于 2012-06-09T19:51:48.023 に答える
1

条件部分は、割り当てられている変数に関係なく、それ自体を解決しようとします。コンパイラは、条件部分に関する限り、RedirectToRouteResult を RedirectResult と同じようにキャストできないため、戻り値として使用するクラスを決定できないという警告を出します。ただし、一方だけが基本クラスにキャストされた場合、もう一方も暗黙的にキャストされるため、最初のキャストは有効です。

 var foo = (someCondition)? 
                  (ActionResult )RedirectToAction("Foo","Bar") :
                  Redirect(someUrl);

しかし、代替案もキャストするだけです:

 var foo = (someCondition)? 
    RedirectToAction("Foo","Bar") :
   (ActionResult)Redirect(someUrl);
于 2012-06-09T19:53:20.007 に答える