怎樣理解C#中的委託代理機制

  很多書和文章都希望能夠從原理層面把代理機制講清楚,從C和C++的指針講到線程安全,從通用類庫講到事件驅動,對於高端玩家,這是很有必要的,但對於初學者,就容易越看越暈,從雲山霧罩,到雲深不知處,本來只有一個概念不懂,現在變成N個了,最後只能投降,不了了之。

  這個概念確實不太容易理解。下面嘗試根據我的理解來說明。

  我們在開發期間最常用的方法所傳遞的參數,一般情況下是某個類型的變量,比如:  

        public long op(long a,long b)
        {
            return a + b;
        }

  現在我給你出個題,你幫我向方法A中傳遞一個方法B,並在A中執行B

  是不是不會了?

  對部分開發者來講,這確實是一個新的概念,或者說是一個新的操作方式,以前沒這樣做過。

  聰明的你可能已經想到了,對,在C#中,此時要用到代理。

  按照方法簽名的定義方式,要傳遞的參數應該是“某個類型 形參”,比如上例中的long a。那麼要傳遞的這個方法的“類型”是什麼呢?

  就是代理,delegate。

  當你要向一個方法A傳遞另一個方法B的時候,要爲這個B方法單獨定義一個“類型”,它要求的有三個要素,參數類型、個數、返回值,只要符合這三項的,都可以傳。

  比如要向方法A傳遞上例中的op(long a,long b)方法,就要像下面這樣定義:  

public delegate long TwoLongsOp(long a, long b);

 

  這時,一個新的“類型”就產生了,所有符合“兩個long型參數、返回值爲long”特點的方法,都符合這個類型定義。

  現在就可以解答我上面出的題了,使用這個類型向方法A傳遞方法B。

  首先要有方法A:  

        public long Atest(TwoLongsOp a)
        {
      return 0;
        }

  顯而易見,這個方法什麼也沒做,但它可以傳一個代理了,離成功近了一點兒。

  下一步開始調用傳過來的參數a,要注意,這個參數是個帶有兩個參數和返回值的方法,調用它也就是執行它。

  怎麼調用呢?

  就像在方法A中調用其它方法一樣。  

        public long Atest(TwoLongsOp a)
        {
            var r = a(2,3);
            return r;
        }

  到這裏,程序是可以編譯的,符合編譯規則,但沒什麼用。因爲我們還沒有定義方法B,也就是方法A的那個“實參”。

  下面我們來定義方法B,方法B一定要符合delegate所定義的格式,參數、返回值,一定要一致:

        public long Btest(long a,long b)
        {
            //其實這裏寫點什麼都行,不一定非得是對a和b的操作,只是對入參進行操作是對它們最大的尊重。
            return a + b;
        }

  接下來就可以正式調用了,噹噹噹當~~向方法A中傳入方法B:  

        public ActionResult Index()
        {
            ViewBag.Message = Atest(Btest).ToString();
            return View();
        }

  我們再定義一個C: 

        public long Ctest(long a, long b)
        {
            return a * b;
        }

 

  接下來可以這樣調用:

        public ActionResult Index()
        {

            ViewBag.Message1 = Atest(Btest).ToString();
            ViewBag.Message2 = Atest(Ctest).ToString();

            return View();
        }

 

   有一點思考一下,代理與方法B和方法C,到底是B和C被代理限制,還是代理爲B和C服務?

 

  想必有人會問,這樣操作的意義是什麼,直接調用Btest不就可以了?

  對,在本例中,是的。但在很多團隊合作的情況下,A不是你寫的,甚至不是你們公司寫的,暴露給你的只是一個方法名,要求傳入符合方法簽名要求的方法。或者你是寫A的人,要給寫B的人留下餘量。

  “委託”或者“代理”一詞應該怎樣理解呢?

  從方法的角度來講,對於參數,它只認識“類型 參數”的模式,所以,方法的“類型”是什麼呢?它沒有內置的類型,所以無法直接傳遞。既然不能直接向A傳遞B,就需要一個“中間人”,定義一個新的“類型”,A和B委託deleate定義的那個東西作爲媒介,把B傳給A。這個新定義的類型,服從A和B的約定(參數類型、個數、返回值)。所以,委託的定義是爲A、B、C服務,它們有需求,所以需要一個合格的中間人。

  有些事情只能是在開發過程中遇到了纔會意識到它的作用和價值,在遇到之前,不太容易理解。本例權當是一次智力遊戲。  

  念念不忘,必有迴響,誠不我欺,共勉。  

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章