为何使用活动?

时间:2009-04-09 03:00:25

标签: c# winforms architecture

我理解事件在C#中的运作方式(在这个领域是一个公平的新手)。我想要了解的是我们使用事件的原因。

您是否知道使用事件的编码良好/架构好的应用程序?

6 个答案:

答案 0 :(得分:10)

提供一个具体的正常世界示例....

你有一个表单,表单有一个列表框。列表框有一个很好的快乐课程。当用户从列表框中选择某些内容时,您想知道并修改表单上的其他内容。

没有事件:

您从列表框派生,覆盖事物以确保您的父级是您期望的表单。 您可以覆盖ListSelected方法或其他东西,它可以操纵父窗体上的其他内容。

有事件: 您的表单会侦听事件,以指示用户选择了某些内容,并操作表单上的其他内容。

不同之处在于,在无事件的情况下,您创建了一个单一用途的类,以及一个与其期望的环境紧密绑定的类。在with events情况下,操作表单的代码已经本地化为您的表单,列表框就是一个列表框。

答案 1 :(得分:7)

您可以在C#中使用事件和代理实现Observer Pattern

以下是描述此类内容的文章的链接:http://blogs.msdn.com/bashmohandes/archive/2007/03/10/observer-pattern-in-c-events-delegates.aspx

enter image description here

答案 2 :(得分:7)

什么是非常有用的是一个使用事件的应用程序的非常重要的例子(猜测它真的有助于测试吗?)

到目前为止的想法是:

为什么要使用事件或发布/订阅?

引发事件时可以通知任意数量的类。

订阅课程不需要知道节拍器(见下面的代码)如何工作,节拍器不需要知道他们将如何回应事件

发布者和订阅者由代表分离。这是非常需要的,因为它使代码更加灵活和强大。节拍器可以改变它如何检测时间而不会破坏任何订阅类。订阅类可以在不打破节拍器的情况下改变他们对时间变化的响应方式。这两个类彼此独立地旋转,这使得代码更容易维护。

class Program
{
    static void Main()
    {
        // setup the metronome and make sure the EventHandler delegate is ready
        Metronome metronome = new Metronome();

        // wires up the metronome_Tick method to the EventHandler delegate
        Listener listener = new Listener(metronome);
        ListenerB listenerB = new ListenerB(metronome);
        metronome.Go();
    }
}

public class Metronome
{
    // a delegate
    // so every time Tick is called, the runtime calls another method
    // in this case Listener.metronome_Tick and ListenerB.metronome_Tick
    public event EventHandler Tick;

    // virtual so can override default behaviour in inherited classes easily
    protected virtual void OnTick(EventArgs e)
    {
        // null guard so if there are no listeners attached it wont throw an exception
        if (Tick != null)
            Tick(this, e);
    }

    public void Go()
    {
        while (true)
        {
            Thread.Sleep(2000);
            // because using EventHandler delegate, need to include the sending object and eventargs 
            // although we are not using them
            OnTick(EventArgs.Empty);
        }
    }
}


public class Listener
{
    public Listener(Metronome metronome)
    {
        metronome.Tick += new EventHandler(metronome_Tick);
    }

    private void metronome_Tick(object sender, EventArgs e)
    {
        Console.WriteLine("Heard it");
    }
}

public class ListenerB
{
    public ListenerB(Metronome metronome)
    {
        metronome.Tick += new EventHandler(metronome_Tick);
    }

    private void metronome_Tick(object sender, EventArgs e)
    {
        Console.WriteLine("ListenerB: Heard it");
    }
}   

我在我的网站上写的完整文章:http://www.programgood.net/

这部分文字来自http://www.akadia.com/services/dotnet_delegates_and_events.html

干杯。

答案 3 :(得分:1)

您始终可以构建自己的发送/接收事件的方式,订阅/取消订阅事件源。但是这种语言为你提供了一种简单/标准的方式,因此这是使用语言“事件”而不是你自己的事件技术的一个很好的理由。

此外,使用语言“事件”可以让你使用反射做各种很酷的事情,因为它是标准化的。

至于为什么要使用事件技术。有各种各样的现实例子,这对于使用事件非常有用和简单。事件的有用性几乎与Windows消息相似。

答案 4 :(得分:1)

在最基本的概念层面,事件是让计算机对你所做的事情作出反应的东西,而不是你被要求对计算机做什么做出反应。当您坐在PC前面运行多个应用程序(包括操作系统),并且每个上下文中有几个可点击的对象供您选择时,事件就是当您选择一个时发生的事情,所有涉及的部分都可以是适当通知。

即使移动鼠标也会启动事件流(例如移动光标)。

答案 5 :(得分:0)

如果您对我们可以使用委托实现相同功能时为什么要使用事件感到困惑,那么答案是:

  1. 客户端(发生订阅的类)在使用事件时不能直接调用delegate上的invoke方法

    instanceOfClassWithDelegate.sampleDelegate.Invoke(); // 事件不可能

  2. 客户端无法在使用事件时列出或清除分配给委托的功能

    instanceOfClassWithDelegate.sampleDelegate = null; // 使用事件时不可能

  3. 事件是一种更好的方式来封装隐式理解的逻辑

此答案的全部功劳归功于此博客:https://dev.to/willydavidjr/why-use-events-instead-of-delegates-in-c-40k8