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

本文关键字:类型 两个 基类 适用于 不适用 继承 条件运算符 | 更新日期: 2023-09-27 18:36:36

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

我的例子是:

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

长格式工作正常的地方:

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

两种返回类型(RedirectToRouteResultRedirectResult)都继承自 ActionResult

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

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

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

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

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

条件运算符无法从其组件(可以是 RedirectToRouteResultRedirectResult )确定结果类型。为了解决此问题,您应该将其中一个(或两个)组件显式转换为基类型:

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

条件部分尝试解析自身,而不考虑分配给哪个变量。编译器发出警告,指出它无法确定将哪个类用作返回值,因为就条件部分而言,RedirectToRouteResult 不能与 RedirectResult 相同。但是,如果只将一端强制转换为基类,则另一端也会隐式强制转换,因此强制转换第一端将是有效的:

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

但也只能投射替代方案:

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