【问题标题】:Help understanding .NET delegates, events, and eventhandlers [duplicate]帮助理解 .NET 委托、事件和事件处理程序 [重复]
【发布时间】:2010-05-11 20:06:02
【问题描述】:

在过去的几天里,我问了几个关于代表 HEREHERE 的问题。 我承认......我不太了解代表。我真的真的真的很想了解和掌握它们。 (我可以定义它们——类型安全函数指针——但由于我对 C 类型语言的经验很少,所以它并没有真正的帮助。)

任何人都可以推荐一些在线资源,这些资源将以一种不假设的方式解释代表吗?

这是我怀疑 VB 实际上阻碍了我的时刻之一,因为它在幕后为我做了一些连接。

理想的资源将只解释什么是委托,而不参考其他任何东西(事件和事件处理程序),将向我展示所有东西是如何连接起来的,解释(正如我刚刚了解到的)委托是类型以及是什么使它们独特的类型(也许使用一点 ildasm 魔法))。然后,该基础将扩展以解释委托如何与事件和事件处理程序相关联,这本身就需要一个很好的解释。最后,该资源可以使用真实示例将所有内容联系在一起,并解释编译器会自动发生什么接线,如何使用它们等。哦,是的,什么时候应该和不应该使用委托,换句话说,缺点和替代方案使用代表。

你说什么?你们中的任何人都可以向我指出可以帮助我开始精通之旅的资源吗?

编辑 最后一件事。理想的资源将解释如何在接口声明中使用和不能使用委托。这真的让我很受挫。

感谢您的帮助。

赛斯

【问题讨论】:

  • 在解释中将委托与事件和事件处理程序分开是非常困难的,因为委托主要是为了使这些功能成为可能而创建的。因此,大多数人经常将代表和事件放在一起考虑,尤其是那些试图解释它们的人。
  • @Seth - 你好,Seth,我正处于你的位置。而且我绝不认为自己是个白痴。我读过 Chris Sell 的解释(不明白),读过教科书中的解释(我知道它是什么,但对何时使用它只有一个模糊的概念),读过堆栈溢出答案:我仍然没有牢牢掌握何时/为什么使用它:你有没有深入了解它?如果是这样,请帮我们解释一下?

标签: c# .net vb.net delegates event-handling


【解决方案1】:

最简单的解释是,委托允许您动态地将方法的“名称”分配给变量或将其作为参数传递(您没有分配字符串名称,它是对方法本身的引用您正在分配给变量)。

然后其他代码可以查看该变量,并稍后调用存储在那里的方法。

委托必须有一个定义(如接口),为此您使用委托关键字。假设我们在某处有一个如下所示的委托定义:

public delegate bool NotifyFriendsDelegate(int intensity);

这基本上只是说任何返回布尔值并采用 int 类型的单个参数的方法(任何地方)都是此委托的实例。因此,委托定义指定了方法必须匹配的形状或签名。

然后说我们有一个这样的类:

public class MyCar
{

   public bool GoVisitMyFriends(NotifyFriendsDelegate thingToDoWhenWeGetThere)
   {
         var doOurFriendsLikeUs = false;
         var driving = new DrivingClass();
         var didWeGetThere = driving.DoTheDrivingNowPlease();

         if(didWeGetThere)
         {
              doOurFriendsLikeUs = thingToDoWhenWeGetThere(11);
         } 
         return doOurFriendsLikeUs;
   }
}

这个类代表一个虚构的汽车,它有一个简单的方法让汽车开到我们朋友家。如果汽车到了我们朋友家,那么我们会想通知我们的朋友我们到了……但是汽车类不知道如何通知我们的朋友。我们可能会非常大声地播放立体声音响,我们可能会吹喇叭,或者我们可能会使用扩音器。

由于 GoVisitMyFriends 方法不知道如何准确地通知我们的朋友,因此它要求调用代码传入对可以执行通知部分的某个方法的引用。 GoVisitMyFriends 不关心你给它的方法,只要方法的形状就像 NotifyFriendsDelegate 的定义一样(它必须返回布尔值并接受一个 int 类型的参数)。

现在让我们创建一个使用我们虚构汽车的简单类:

public class MyFunClass()
{
    public bool NotifyFriendsByRammingTheirHouse(int howHard)
    {
         var rammingModule = new RammingModule();
         return rammingModule.RamFriendsHouse(howHard); 
    }

    public bool DoSomethingFun()
    {
         var car = new MyCar();
         var areWeCool = car.GoVisitMyFriends(NotifyFriendsByRammingTheirHouse);
         return areWeCool;
    }
} 

该类包含一个符合 NotifyFriendsDelegate 签名的方法。它包含一个名为 DoSomethingFun 的方法,该方法创建 MyCar 的一个实例,然后调用 GoVisitMyFriends 方法。它传入了 NotifyFriendsByRammingTheirHouse 方法,这样 MyCar 类就知道当我们到达那里时我们想如何表达对朋友的爱。

这是我能想到的最简单的委托用法。

顺便说一句:我一直发现将事件视为包含委托方法集合的特殊变量很有用。可以为事件分配任意数量(从零到无穷大)的委托,所有委托都将在事件被调用时被调用。事件只是可以被视为“一件事”的代表组。

【讨论】:

  • 我讨厌这句话:“这基本上只是说任何返回布尔值并采用 int 类型的单个参数的方法(任何地方)都是此委托的实例”。但我不能怪你。这个话题很难解释。我什至不敢尝试。在我看来,更好的类比是匿名函数就像一个字面量,普通函数就像一个命名常量,而委托变量很好......一个变量。
  • 呵呵,我明白你的意思了。如果您深入研究技术实现,那么我的回答中几乎没有什么是“真实”或“准确”的。但我发现,这种关于委托的一般性思考方式非常适合引导开发人员对委托的含义有一个有用的理解。从那里,可以发展出更准确的画面......但很难理解模糊的概括概念。
  • 确实,事件是代表集合的包装。多播委托对 imo 有用的唯一情况。
【解决方案2】:
【解决方案3】:

我最喜欢的解释来自 Chris Sells:

http://sellsbrothers.com/public/writing/delegates.htm

【讨论】:

    【解决方案4】:

    查看 C# 编程指南 - here 是代表部分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多