3

我从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返回RedirectToAction一个子类ActionResult(通过 F12 验证)并且该子类是函数的返回值,因此它应该是自动兼容的。或者至少,根据我对 C# 的了解,两种代码都可以编译,或者它们都不能编译。

更笼统地说,这个问题可以重新表述如下:

假设我有 A、B 和 C 类

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

并假设以下功能有效

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

为什么以下单行代码无法编译?

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

2 回答 2

6

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

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

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

更新:我没有看到你已经在你的问题中做了演员,我很抱歉。

于 2013-01-03T17:37:32.150 回答
2

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

return (Url.IsLocalUrl(returnUrl)) ? (ActionResult)Redirect(returnUrl) : (ActionResult)RedirectToAction("Index", "Home");
于 2013-01-03T17:38:47.017 回答