我需要一个非常简单的例子来了解事件.我感觉很难理解互联网或书籍中的例子.
解决方法
这是一个公开事件的类的简单实现.
public class ChangeNotifier { // Local data private int num; // Ctor to assign data public ChangeNotifier(int number) { this.num = number; } // The event that can be subscribed to public event EventHandler NumberChanged; public int Number { get { return this.num; } set { // If the value has changed... if (this.num != value) { // Assign the new value to private storage this.num = value; // And raise the event if (this.NumberChanged != null) this.NumberChanged(this,EventArgs.Empty); } } } }
这个类可以使用如下所示:
public void SomeMethod() { ChangeNotifier notifier = new ChangeNotifier(10); // Subscribe to the event and output the number when it fires. notifier.NumberChanged += (s,e) => Console.Writeline(notifier.Number.ToString()); notifier.Number = 10; // Does nothing,this is the same value notifier.Number = 20; // Outputs "20" because the event is raised and the lambda runs. }
关于控制流,执行流入SomeMethod().我们创建一个新的ChangeNotifier,从而调用它的构造函数.这将值10分配给私有num成员.
然后我们使用=语法订阅该事件.此运算符在右侧接受委托(在我们的示例中,该委托是lambda)并将其添加到事件的委托集合中.此操作不会执行我们在ChangeNotifier中编写的任何代码.如果您愿意,可以通过事件的添加和删除方法对其进行自定义,但很少需要这样做.
然后我们对Number属性执行几个简单的操作.首先我们分配10,它在Number属性上运行set方法,其值为10.但是num成员的值已经为10,因此初始条件的计算结果为false,没有任何反应.
然后我们用20做同样的事情.这次值不同,所以我们将新值赋给num并触发事件.首先,我们验证事件不是null.如果没有订阅它,它就为null.如果它不为null(即,如果有东西订阅它),我们使用标准方法/委托语法来激活它.我们只需使用事件的参数调用事件.这将调用已订阅事件的所有方法,包括将执行Console.WriteLine()的lambda.
如果一个线程可以在Number的setter中,而另一个线程取消订阅一个监听器,Henrik已经成功地挑选了存在的潜在竞争条件.对于那些还不了解事件如何工作的人来说,我不认为这是一个常见的情况,但是如果你担心这种可能性,请修改以下几行:
if (this.NumberChanged != null) this.NumberChanged(this,EventArgs.Empty);
是这样的:
var tmp = this.NumberChanged; if (tmp != null) tmp(this,EventArgs.Empty);