我不明白纯委托和事件字段之间的区别

hqt*_*hqt 5 c# events delegates

代表:我明白了.但是当我搬到活动时,很多事情我都不太了解.我在网上读过书,MSDN和一些简单的例子,它们都有相同的结构.例如,这是链接:事件示例

我拿第一个例子,作者说这是关于C#事件最简单的例子.

这是他的代码:

public class Metronome
{
    public event TickHandler Tick;
    public EventArgs e = null;
    public delegate void TickHandler(Metronome m, EventArgs e);
    public void Start()
    {
        while (true)
        {
            System.Threading.Thread.Sleep(3000);
            if (Tick != null)
            {
                Tick(this, e);
            }
        }
    }
}

public class Listener
{
    public void Subscribe(Metronome m)
    {
        m.Tick += new Metronome.TickHandler(HeardIt);
    }
    private void HeardIt(Metronome m, EventArgs e)
    {
        System.Console.WriteLine("HEARD IT");
    }
}

class Test
{
    static void Main()
    {
        Metronome m = new Metronome();
        Listener l = new Listener();
        l.Subscribe(m);
        m.Start();
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以注意到:public event TickHandler Tick.当我改为时public TickHandler Tick,程序仍然运行相同.但我理解的新线路因为它只是一个纯粹的代表.

所以,我的问题是:event关键字的真正目的是什么:public event TickHandler Tick.这非常重要,因为所有示例总是这样使用,但我无法解释原因.

谢谢 :)

Jon*_*eet 9

代表和事件是相关的概念,但它们不是一回事."代表"一词往往有两个含义(经常被掩盖):

  • 委托类型,类似于单个方法接口.(存在显着差异,但这是一个合理的起点.)
  • 通常通过方法组创建的该类型的实例,以便在"调用"委托时调用该方法.

事件既不是那些事件.它是一种类型的成员 - 一对添加/删除方法,让代理人订阅或取消订阅该事件.使用foo.SomeEvent += handler;或时使用add和remove方法foo.SomeEvent -= handler;.

这非常类似于属性实际上是一对get/set方法(或者可能只是两者中的一个).

当您声明类似字段的事件时:

public event TickHandler Tick;
Run Code Online (Sandbox Code Playgroud)

编译器将成员添加到您的类中,有点像这样:

private TickHandler tick;

public event TickHandler
{
    add { tick += value; }
    remove { tick -= value; }
}
Run Code Online (Sandbox Code Playgroud)

它比这复杂一点,但这是基本的想法 - 它是一个简单的事件实现,就像一个自动实现的属性.从类中,您可以访问支持字段,而在课外,您最终只会使用该事件.

我个人认为很遗憾,类似字段的事件的声明看起来非常委托类型的字段 - 它导致一些答案中发现的一些误导性(IMO)语句,就像event关键字"修改"一样"一个现场宣言 - 实际上它意味着你宣布一些完全不同的东西.我认为,如果类似字段的事件看起来更像是自动实现的属性,那就更清楚了

// Not real C#, but I wish it were...
public event TickHandler Tick { add; remove; }
Run Code Online (Sandbox Code Playgroud)

我有一篇文章更详细,你可能会发现它很有用.


use*_*016 7

event关键字基本上限制了您的操作delegate.您无法再使用=操作员手动分配它.

您只能逐个添加(使用+=)或删除(使用-=)事件中的代理.这样做是为了防止某些订户"覆盖"其他订阅.

因此,你做不到: m.Tick = new Metronome.TickHandler(HeardIt)

  • 请注意,这些限制仅在声明`event`的类型之外.在里面,你仍然可以做任何你想做的事情,这样你就可以做一些事情,比如`Tick(this,e)`.您可以将其视为透明地创建`private TickHandler`以及通过+ =和 - =访问的公共添加/删除方法. (2认同)
  • 我认为说它"限制操作"是误导性的 - 它从根本上宣告了一种不同类型的成员(一种事件).我认为将事件和代表在心理上分开是非常有帮助的. (2认同)