用三元运算符理解C#编译错误

我已经从Wrox Professional ASP.NET 4.0 MVC 4书籍,第179页(“了解Web应用程序中的安全性向量”一章)中复制了以下代码,只需稍加修改即可将其protected并作为实用方法存储在我的抽象应用程序中 -宽Controller

 protected ActionResult RedirectToLocal(string returnUrl) { if (Url.IsLocalUrl(returnUrl)) { return Redirect(returnUrl); } else { return RedirectToAction("Index", "Home"); } } 

上面的代码旨在保护MVC应用程序免受开放重定向攻击,这些攻击不是问题的主题。

代码显然是格式良好,编译,我相信它的工作原理。

当“巧妙地”将上面的代码更改为以下单行时,就会出现问题

 return (Url.IsLocalUrl(returnUrl)) ? Redirect(returnUrl) : RedirectToAction("Index", "Home"); 

上面的单行应该与扩展代码完全相同(不,ReSharper不建议我替换,这是我的主动)。

编译错误如下: there is no implicit conversion between System.Web.Mvc.RedirectResult and System.Web.Mvc.RedirectToRouteResult

然后ReSharper来帮助并建议以下修改

 return (Url.IsLocalUrl(returnUrl)) ? (ActionResult) Redirect(returnUrl) : RedirectToAction("Index", "Home"); 

问题是“为什么我必须强制转换Redirect方法”?

由于RedirectRedirectToAction返回ActionResult的子类(通过F12validation),并且该子类是函数的返回值,因此它应该是自动兼容的。 或者至少,根据我对C#的了解,要么两个代码都编译,要么两者都不编译。

更一般地说,问题可以重新拟定如下:

假设我有A,B和C类

 abstract class A {} class B: A{} class C: A{} 

并假设以下function有效

 private A Function(){ if (condition) return new B(); else return new C(); } 

为什么下面的单行程不能编译?

 private A Function(){ return (condition) ? new B(): new C(); } 

它不会编译,因为编译器根据两个返回值之一决定一个内容的返回类型。 由于类型B不是从类型C派生,或者反过来,这两种类型不是互斥的,并且if(作为一个整体)的返回类型不能以这种方式导出。

如果您希望在单行中执行此操作,则必须将返回值强制转换为要返回的类型,即类型A.

 private A Function(){ return (condition) ? ((A)new B()): ((A)new C()); } 

更新:我没有看到你已经在你的问题中进行了投射,我的道歉。

编译器期望在条件语句中使用相同的返回类型,因此它希望这两者都是相同的类型。 如果将选项转换为ActionResult,它将起作用。 您可以通过仅转换最后一个来与编译器相处。

 return (Url.IsLocalUrl(returnUrl)) ? (ActionResult)Redirect(returnUrl) : (ActionResult)RedirectToAction("Index", "Home");