怎样理解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服务,它们有需求,所以需要一个合格的中间人。

  有些事情只能是在开发过程中遇到了才会意识到它的作用和价值,在遇到之前,不太容易理解。本例权当是一次智力游戏。  

  念念不忘,必有回响,诚不我欺,共勉。  

  

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