条件运算符不适用于继承相同基类型的两种类型

时间:2012-06-09 19:46:46

标签: c# asp.net-mvc conditional-operator

当条件运算符(?:)与从单个基类型继承的两种类型一起使用时,它们怎么会不起作用?

我的例子是:

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

长形式可以正常工作:

ActionResult foo;

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

返回类型RedirectToRouteResultRedirectResult都继承自ActionResult

3 个答案:

答案 0 :(得分:13)

  

当使用从单个基类型继承的两种类型时,条件运算符(?:)怎么不起作用?

根据语言规范,条件表达式的类型必须 第二个操作数的类型第三个​​操作数的类型。编译器不会尝试查找公共基类型,也不会尝试将两个操作数都转换为其他类型。表达式的 use 不会影响其类型的确定方式 - 因此变量赋值在这里无关紧要。

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

有关更多详细信息,请参阅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;

答案 1 :(得分:1)

条件运算符无法从其组件中确定结果类型,可能是RedirectToRouteResultRedirectResult。为了解决这个问题,您应该将组件中的任何一个(或两个)明确地转换为基类型:

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

答案 2 :(得分:1)

无论分配给它的变量如何,条件部分都会尝试自行解析。编译器发出警告,它无法确定将哪个类用作返回值,因为就条件部分而言,RedirectToRouteResult不能与RedirectResult一样强制转换。但是如果只有一方被强制转换为基类,那么另一方也被隐式转换,所以强制转换第一方是有效的:

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

但也只是推销替代方案:

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