Zrozumienie błędu kompilacji C # z operatorem trójskładnikowym
Skopiowałem następujący kod zWrox Professional ASP.NET 4.0 MVC 4
książka, strona 179 (Rozdział „Zrozumienie wektorów bezpieczeństwa w aplikacji internetowej”) z małą modyfikacjąprotected
i przechowywanie jako metoda użyteczności w mojej abstrakcyjnej aplikacjiController
protected ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
Powyższy kod ma na celu zabezpieczenie aplikacji MVC przed atakami otwartego przekierowania, które nie są przedmiotem pytania.
Kod jest oczywiście dobrze sformatowany, kompiluje się i ufam, że działa.
Problem pojawia się, gdy „mądrze” zmienia powyższy kod na następujący jeden liner
return (Url.IsLocalUrl(returnUrl)) ? Redirect(returnUrl) : RedirectToAction("Index", "Home");
Powyższy jeden liner powinien robić dokładnie to samo, co rozszerzony kod (nie, ReSharper nie sugerował, żebym go zastąpił, to była moja inicjatywa).
Błąd kompilacji jest następujący:there is no implicit conversion between System.Web.Mvc.RedirectResult and System.Web.Mvc.RedirectToRouteResult
.
ReSharper przychodzi wtedy z pomocą i sugeruje następującą modyfikację
return (Url.IsLocalUrl(returnUrl)) ? (ActionResult) Redirect(returnUrl) : RedirectToAction("Index", "Home");
Pytanie brzmi „dlaczego muszę rzucać metodę przekierowania”?Od kiedy obojeRedirect
iRedirectToAction
zwróć podklasęActionResult
(zweryfikowane przez F12) i ta podklasa jest wartością zwracaną przez funkcję, powinna być automatycznie kompatybilna. A przynajmniej, z mojej wiedzy o C #, albo oba kody się kompilują, albo oba nie.
Mówiąc bardziej ogólnie, pytanie można przeformułować w następujący sposób:
Załóżmy, że mam klasy A, B i C
abstract class A {}
class B: A{}
class C: A{}
Załóżmy, że działa następująca funkcja
private A Function(){
if (condition) return new B();
else return new C();
}
Dlaczego następujący kompilator nie jest kompilowany?
private A Function(){
return (condition) ? new B(): new C();
}