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 メソッドをキャストする必要があるのか​​」ということです。

と の両方が (F12 で検証された)のサブクラスを返し、Redirectそのサブクラスが関数の戻り値であるため、自動的に互換性があるはずです。または、少なくとも、私の C# の知識では、両方のコードがコンパイルされるか、両方ともコンパイルされないかのどちらかです。RedirectToActionActionResult

より一般的に言えば、この質問は次のように再定式化できます。

クラス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

コンパイラーは、2つの戻り値のいずれかに基づいてワンライナーの戻りタイプを決定するため、コンパイルされません。タイプBはタイプCから派生しないため、またはその逆であるため、2つのタイプは相互に排他的ではなく、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 に答える