.netで面白い「拡張方法」(Extension Method)

6885 ワード

ASPを見ています.NetMVCコードのとき、こんな呼び出しがありました.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);

ここでroutesはRouteCollectionクラスであり、RouteCollectionクラスにはMapRouteメソッドは存在しない.MapRouteメソッドはRouteCollectionExtensionsクラスのメソッドであり、メタデータから取得したRouteCollectionExtensionsの説明は以下の通りである.
    public static class RouteCollectionExtensions
{
public static VirtualPathData GetVirtualPathForArea(this RouteCollection routes, RequestContext requestContext, RouteValueDictionary values);
public static VirtualPathData GetVirtualPathForArea(this RouteCollection routes, RequestContext requestContext, string name, RouteValueDictionary values);
public static void IgnoreRoute(this RouteCollection routes, string url);
public static void IgnoreRoute(this RouteCollection routes, string url, object constraints);
public static Route MapRoute(this RouteCollection routes, string name, string url);
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults);
public static Route MapRoute(this RouteCollection routes, string name, string url, string[] namespaces);
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints);
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces);
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces);
}

このクラスは表面的には独立したクラスであり、他のクラスから継承されたものではなく、Interfaceも実現されていませんが、注意してください.
  • まずstaticクラスであり、その方法もstatic
  • である.
  • 実際には、そのメソッドの最初のパラメータは「this RouteCollection」であり、タイプの前に「this」
  • が追加されています.
    これは何を表していますか.実はこれです.Netの面白い使い方です.それはクラスを拡張する方法ですが、このクラスのコードを直接修正しないで、次の簡単な例があります.
        class Hello
    {
    private string m_strHello = "Hello";
    public string String { get { return m_strHello; } set { m_strHello = value; } }
    }

    static class HelloExtensions
    {
    public static void AppendWorld(this Hello hello)
    {
    hello.String += " World";
    }
    }

    class Program
    {
    static void Main(string[] args)
    {
    Hello hello = new Hello();
    hello.AppendWorld();
    Console.WriteLine(hello.String);
    }
    }

    「AppendWorld」という方法は「Hello」というクラスに属しているように見えます.
    これには、クラスのパッケージを破ることはできません.拡張方法は、拡張するクラスのpublicメンバーにアクセスするしかありません.他のメンバーは動けません.