在事件处理C#中制作事件变量的需求是什么?

时间:2014-02-01 11:10:47

标签: c# events event-handling

我读到了如何创建事件处理程序,我发现用于创建委托和事件变量的所有教程和文章。我不明白为什么他们使用事件变量,因为我们可以像使用代码一样使用委托来创建事件处理程序:

namespace EventsTest
{     
    public class Counter
    {
        public delegate void ReachedEventHandler(object sender);
        public ReachedEventHandler fireEvent;
        // public event ReachedEventHandler fireevent;
        private int counter = 0;

        public void Add(int x, int toReach)
        {
            counter += x;
            if (counter == toReach && fireEvent != null)
               fireEvent(this);
        }
    }

    public class Test
    {
        public static void Main()
        {
            Counter x = new Counter();
            x.fireEvent += new Counter.ReachedEventHandler(CounterReachedEventHandler);
            x.Add(1, 1);
        }

        private static void CounterReachedEventHandler(object sender)
        {
            Console.WriteLine("Reached!");
        }
    }
}

这会有效,那么制作事件变量的需求是什么?

谢谢!

3 个答案:

答案 0 :(得分:4)

event关键字保证封装:您无法在fireEvent之外调用或修改Counter。外面唯一可用的操作是订阅和取消订阅(+=-=)。

关于您的代码的一些注释:

  1. 一般情况下,您应该使用EventHandler委托,而不是在自定义ReachedEventHandler的情况下定义您自己的等效文件(EventHandler<TEventArgs>)和EventArgs

  2. 您的ReachedEventHandler未遵循事件的标准惯例。他们应该有两个参数(object senderTEventArgs args,其中TEventArgsEventArgs或子类)并返回void

  3. 显式new Counter.ReachedEventHandler()来电也是不必要的。

答案 1 :(得分:3)

使用event优于delegate的优点是编译器为您生成了添加/删除pluming。例如,如果你有:

public event EventHandler<EventArgs> FooEvent;

然后编译器会自动为您生成addremove方法。这些方法将填充底层委托,并将以线程安全的方式填充,这样您就不必担心锁定底层委托。

此外,您班级的任何消费者只能向代表添加和删除处理程序,他们将无法对代表进行调用(即他们无法举起活动) 。只有你的班级才能做到这一点。

答案 2 :(得分:2)

这是阻止某人编写这样的代码:

class MyClass {
    public MyClass(Counter counter) {
        // Myhahaha, your base belongs to me!
        counter.fireEvent = new ReachedEventHandler(reached); 
    }
    private void reached(object sender) {
        // etc...
    }
}

这会消除任何其他正在侦听事件的代码,它们的事件处理程序将永远不会被调用。

事件是委托对象的访问者,它只允许+ =添加,而= =删除事件处理程序。进一步限制你永远不能删除别人的事件处理程序。与字段的访问者,属性进行比较。只允许获取和设置,它会阻止其他代码直接写入字段值。