13

为什么条件运算符 ( ?:) 在与从单个基类型继承的两种类型一起使用时不起作用?

我的例子是:

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

为什么条件运算符 (?:) 在与从单个基类型继承的两种类型一起使用时不起作用?

根据语言规范,条件表达式的类型必须第二个操作数的类型或第三个操作数的类型。编译器不会尝试找到一个通用的基本类型,或者两个操作数都可以转换为的另一种类型。表达式的使用不会影响其类型的确定方式——因此变量赋值在这里无关紧要。

至于为什么这样定义语言 - 它使指定、实现、测试和预测变得相当简单。这在语言设计中相当普遍——从长远来看,保持语言简单通常是一个更好的选择,即使它在某些特定情况下会变得更加尴尬。

有关更多详细信息,请参阅 C# 4 规范的第 7.14 节。

将第二个或第三个操作数转换为条件表达式实际需要的类型是解决问题的方法。请注意,这经常出现的另一种情况是可为空的类型:

// 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 回答