使用特定示例了解 C# 中的委托和事件

本文关键字:事件 了解 | 更新日期: 2023-09-27 17:50:23

所以我已经到了理解事件和代表的地步。

我过度理解代表的用法。关于委托,我唯一关心的是是否可以将委托配置为使用与事件无关的函数......如果是,如何为委托定义的函数编写逻辑?(我想这样的功能并没有多大意义,但很高兴知道。

至于事件...我很难理解它。我明白事件是一个函数,当代码中发生某些事情时执行。但是,我没有得到创建事件的过程。部分地。

对于这个问题,我将使用加里·威洛比(Gary Willoughby(的回答:https://stackoverflow.com/a/803528/1104766它发布在一个我试图理解整个主题的问题上。

我在上面的例子中没有得到什么:

MyObject.OnMaximum += new MyEventHandler(MaximumReached);首先,如何创建一个委托的实例,并在需要 2 个变量时只传递 1 个变量?一定是我错过了什么...
关于这一行的第二件事是,new ...()实例被添加到驻留在MyObject中的OnMaximum函数中,该函数是MyClass的实例 - 如果可以做这样的事情,究竟是什么OnMaximum它也从未真正定义过!

      if(OnMaximum != null) {
        OnMaximum(this, new MyEventArgs("You've entered " +
          value.ToString() +
          ", but the maximum is " +
          Maximum.ToString()));
      }

至于这部分,OnMaximum被称为,但它的逻辑从未在代码的任何地方真正定义过,那么结果会是什么?显然,我猜应该是文字"你已经输入了......"。但我的问题是更具体地说,函数/事件收到的值到底发生了什么?

为了清楚起见,我用粗体标记了所有问题。

附言,我知道这个问题通常已经发布了几次。
请注意,此特定问题是指其他成员撰写的答案,此处提出的问题特定于此示例。这就是为什么在谷歌中找不到这样的答案。
不过,为了记录,我在发布之前确实进行了搜索,并且我确实尝试了理解,但我想示例是我理解某些东西的最佳方式,尤其是当我缺乏英语CS词汇知识时。

使用特定示例了解 C# 中的委托和事件

我想你可能患有过量的句法糖!

你看,所有事件都是一个委托。 实际上,老实说,这是一个可能被null的代表集合。

让我们举个例子:

public class Alarm
{
    public delegate void AlarmEvent();
    // my secret stuff
    // raise it!
    public void Ring()
    {
        if(OnAlert != null)
           OnAlert();
    }
    public event AlarmEvent OnAlert;
}

所有的事件关键字在这里为我们提供的,是添加和删除该事件的侦听器的能力......

Alarm a = new Alarm();
a.OnAlert += myevent;
a.OnAlert += myotherevent;

另一方面,委托的工作方式与我们刚才描述的完全一样,但更类似于函数指针。 想象一个抽象渲染器,我可以这样制作类:

public abstract class Renderer
{
    protected abstract void RenderImpl();
}

这意味着,我必须从该渲染中得出。 但是,如果该渲染器接受委托呢?

public abstract class Renderer
{
    public delegate void RenderDelegate();
    public Renderer(RenderDelegate) { /* ... */ }
}

我们现在正在分离构图。

我得到了什么? 好不好? 就事件而言,我允许公众成为我班级的观察者。 他们可以做出反应。 在第二种情况下,我定义一个用户提供的委托来执行利基功能,同时我保留大部分控制权。

委托和事件大多是一回事 - 但我们所做的设计选择决定了哪一个是合适的。

为了解决您的其他问题,您提出了一个事件与委托的很好的例子。 如果我们要更改上面的警报类,以允许委托返回truefalse,那么会发生什么?

我们会得到几个观察者返回 true,但谁是对的,我们如何检查它们?

然而,沿着单一代表路线... "渲染成功"或"渲染失败"。 更改此单个委托并不是什么大问题。 我们可以预测地测试我们的渲染器是否完成了这项工作:

if(!delegate_->Invoke())
    fallBackCode();

我们不能在事件中做到这一点。 好吧,不可预测。

更简单地说,当您想广播某些内容并让其他人在收到该事件后执行某些操作时,事件就存在。 炸弹爆炸了... 奔跑,躲藏,打电话给国民警卫队,关掉烤箱,或者躲避和掩护。

委托

允许您在不更改模型的情况下更改功能(委托遵循签名! 代表的一个很好的例子是当你打电话给List<T>.Sort时。 那是代表。 它有一个签名。

但是您也可以将它们用于更高级的事情,例如在不诉诸接口的情况下更改Renderer类,以及能够提供用户定义的"代码片段"。 我想这里最简单的类比是 Win32 中的所有者绘制的控件。 无需覆盖整个类,无需提供接口并编写大量代码。 只需更改在组合框中呈现项目的位即可。 代表们是你如何实现这一目标的很好的例子。

MSDN 的教程将回答您的所有问题:

代表: http://msdn.microsoft.com/en-us/library/aa288459(v=vs.71(.aspx

事件:http://msdn.microsoft.com/en-us/library/aa645739(v=vs.71(.aspx

class Program
    {
        static void Main(string[] args)
        {
            Parent p = new Parent();
        }
    }
    ////////////////////////////////////////////
    public delegate void DelegateName(string data);
    class Child
    {
        public event DelegateName delegateName;
        public void call()
        {
            delegateName("Narottam");
        }
    }
    ///////////////////////////////////////////
    class Parent
    {
        public Parent()
        {
            Child c = new Child();
            c.delegateName += new DelegateName(print);
            //or like this
            //c.delegateName += print;
            c.call();
        }
        public void print(string name)
        {
            Console.WriteLine("yes we got the name : " + name);
        }
    }

加油伙计们!你们所有人都成功地使代表们:)复杂化!

我将尝试在这里留下一个提示:一旦我在 Javascript 中意识到 jquery ajax 调用,我就理解了代表。 例如:ajax.send(url, data, successcallback, failcallback( 是函数的签名。 如您所知,它将数据发送到服务器 URL,作为响应,它可能是 200OK 或其他错误。如果发生任何此类事件(成功/失败(,您需要执行一个函数。因此,这就像一个函数的占位符,能够提及成功或失败。该占位符可能不是很通用 - 它可能接受一组参数,并且可能/可能不会返回值。这种占位符的声明,如果在 C# 中完成,则称为委托!由于 javascript 函数对参数数量不严格,您只会将它们视为通用占位符......但是 C# 有一些严格的声明...这归结为代表声明!!

希望对您有所帮助!