这是公开事件的类的简单实现。
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
member.
然后我们使用以下方式订阅该事件+=
句法。该运算符在右侧获取一个委托(在我们的例子中,该委托是一个 lambda)并将其添加到事件的委托集合中。此操作不会执行我们在中编写的任何代码ChangeNotifier
。它可以通过定制add
and remove
如果您愿意,可以使用事件的方法,但很少需要这样做。
然后我们执行一些简单的操作Number
财产。首先我们分配10
,它运行set
方法上的Number
财产与value = 10
。但是num
会员的价值已经是10
,因此初始条件评估为 false 并且什么也没有发生。
然后我们做同样的事情20
。这次值不同了,所以我们将新值赋给num
并触发该事件。首先我们验证该事件不为空。如果没有任何内容订阅它,则它为空。如果它不为空(即,如果某事is订阅它),我们使用标准方法/委托语法触发它。我们只需使用事件的参数来调用该事件。这将调用所有已订阅该事件的方法,包括将执行以下操作的 lambdaConsole.WriteLine()
.
Henrik 已成功地挑剔了如果一个线程可以进入则存在的潜在竞争条件。Number
的设置器,而另一个线程正在取消订阅侦听器。对于还不了解事件如何工作的人来说,我不认为这是常见情况,但如果您担心这种可能性,请修改以下行:
if (this.NumberChanged != null)
this.NumberChanged(this, EventArgs.Empty);
是这样的:
var tmp = this.NumberChanged;
if (tmp != null)
tmp(this, EventArgs.Empty);