A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张少甫 中级黑马   /  2012-9-17 10:37  /  3476 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 张少甫 于 2012-9-17 10:46 编辑

委托属于类?还是方法?还是其他?

评分

参与人数 1技术分 +1 收起 理由
郑文 + 1

查看全部评分

8 个回复

正序浏览
其实,对于已经创建好的方法,其本身无所谓隶属于谁,哪个线程调用,它便可被看做是谁的方法。这种情况与方法的跨类调用不同 —— 因为一个方法隶属于哪个类本是一目了然的事情。在这里,你可以稍稍回想一下我们在前面得出的一个很关键的结论:C#中的委托实例能够非常灵活的兼容对象与方法的特质——我认为这是上述技术得以实现的关键所在!

  在C#中,要人为控制一个方法隶属于哪个线程不太容易,然而,要控制一个对象属于某一个固定的线程却很简单——只要让目标对象在这个线程里被创建就可以了!这就可以解释为什么上述代码要凭借委托来实现了:既然我们不能控制一个方法隶属于某一个线程,那么便不妨通过控制委托这种特殊的对象来间接控制挂载于它上面的方法和相关线程的隶属关系!这便实现了如何安全的通过委托进行方法的跨线程调用。

  我们再回过头来看,事实上,SetText()方法第一次被调用时确实被看做是子线程的方法,因为是子线程调用了它,然而,第二次的情况不同,显然,方法的第二次调用触发时,依然是子线程相对占据统治地位,并且恰恰是它控制委托对象对目标方法进行了第二次调用。然而该方法却是被主线程中创建的委托对象调用的,自然而然也就隶属于主线程了。这论证了先前我关于“假如我们通过已声明的委托对象来调用相应的方法,C#的编译器将自动将其作为本类的声明方法来对待(从C#编译器的安全角度来论证,这个说法是行得通的)”这个观点,只不过这里的编译器安全性已不再是针对类对象,而是针对线程对象而言了。

  这样一来,讨论的中心再度回归到“委托(实例化对象)兼具对象与方法二者的特性”这个主题上来:委托实例本身就是以对象的形式而存在的,同时它又可以挂接方法,使其本身可以灵活调用这些方法——也就是说,借助委托,我们实现了方法的对象化

评分

参与人数 1技术分 +2 收起 理由
郑文 + 2

查看全部评分

回复 使用道具 举报
呵呵,委托就是C里面的函数指针,,再说简单点,就是指向函数的一个指针。定义一个委托就是定义一下你这个委托可以指向什么类型 的 函数.....

评分

参与人数 1技术分 +1 收起 理由
宋天琪 + 1

查看全部评分

回复 使用道具 举报
委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。
给你一个我的理解:委托就像你在某个地方占了一个“坑”,而这个“坑”里能放得东西就是和你声明的委托传入参数和返回值一样的方法。如:delegate string MathAction(string a);这个“坑”里能放得方法就是类似于public string s(string a){};你可以调用这个“坑”而这个“坑”里放那个方法它就会去调用那个方法。(还有一点这个“坑”里可以放多个方法它就会依次调用你的方法 是不是很强大)

评分

参与人数 1技术分 +1 收起 理由
郑文 + 1

查看全部评分

回复 使用道具 举报
委托类型的声明与方法签名相似, 有一个返回值和任意数目任意类型的参数:
  1. public delegate void TestDelegate(string message);
  2. public delegate int TestDelegate(MyType m, long num);
复制代码
delegate 是一种可用于封装命名或匿名方法的引用类型。 委托类似于 C++ 中的函数指针;但是,委托是类型安全和可靠的。
给你个例子看看:

  1. // Declare delegate -- defines required signature:
  2. delegate double MathAction(double num);

  3. class DelegateTest
  4. {
  5.     // Regular method that matches signature:
  6.     static double Double(double input)
  7.     {
  8.         return input * 2;
  9.     }

  10.     static void Main()
  11.     {
  12.         // Instantiate delegate with named method:
  13.         MathAction ma = Double;

  14.         // Invoke delegate ma:
  15.         double multByTwo = ma(4.5);
  16.         Console.WriteLine("multByTwo: {0}", multByTwo);

  17.         // Instantiate delegate with anonymous method:
  18.         MathAction ma2 = delegate(double input)
  19.         {
  20.             return input * input;
  21.         };

  22.         double square = ma2(5);
  23.         Console.WriteLine("square: {0}", square);

  24.         // Instantiate delegate with lambda expression
  25.         MathAction ma3 = s => s * s * s;
  26.         double cube = ma3(4.375);

  27.         Console.WriteLine("cube: {0}", cube);
  28.     }
  29.     // Output:
  30.     // multByTwo: 9
  31.     // square: 25
  32.     // cube: 83.740234375
  33. }
复制代码
我刚开始学委托的时候也很难理解,这个要多做练习才能慢慢理解

评分

参与人数 1技术分 +2 收起 理由
郑文 + 2

查看全部评分

回复 使用道具 举报
委托的声明方式跟类是相似的,实际储存的是函数地址(是类型安全的),可以将委托传递给函数作为回调函数使用

评分

参与人数 1技术分 +1 收起 理由
宋天琪 + 1

查看全部评分

回复 使用道具 举报
所有委托都从System.Delegate继承而来并且有一个调用列表,这是在调用委托时所执行方法的一个链接列表。产生的委托可以用匹配的签名引用任何方法,没有为具有返回类型并在调用列表中包含多个方法的委托定义返回值。
委托声明定义一个类,它是从System.Delegate类派生的类。委托实例封装了一个调用列表,其中列出了一个或多个方法,每个方法称为一个可调用实体。对于实例方法,可调用实体由一个实例和该实例的方法组成;对于静态方法,可调用实体仅由一个方法组成。如果用一组合适的参数来调用一个委托实例,则该委托实例所封装的每个可调用实体都会被调用,并且使用上述同一组参数。
委托实例的一个有用的属性是它既不知道,也不关心其封装方法所属类的详细信息,对它来说最重要的是这些方法与该委托的类型兼容。即只要方法的返回类型和参数表是相同的,则方法与委托类型兼容,方法的名称不一定要与委托类相同。

评分

参与人数 1技术分 +1 收起 理由
郑文 + 1

查看全部评分

回复 使用道具 举报
1. 委托可以把一个方法作为参数代入另一个方法;
2. 委托可以理解为指向一个函数的引用。
回复 使用道具 举报
委托可以简单的从字面去理解,即“委托别人去执行某些操作”,也就是说执行一个操作,而这个操作过程自身并不知道,
只是委托过来让你去执行而已。
   一般事件的初始化需要绑定一个事件处理函数,那么当事件触发的时候,处理函数会被调用,也就是说在事件处理函数可以明确的知道,
此事件是被触发了。例如,点击窗体的上的Button,它会把Click事件反馈给窗体。很明显,委托是处理对象之间的信息交互。

评分

参与人数 1技术分 +1 收起 理由
郑文 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马