与 C# 编程世界中的其他一切一样,事件概念也遵循特定规则并具有自己的语法。措辞如下:
- 定义为EventHandler 的事件实际上只是一种特殊方法(委托)签名 -
public delegate void EventHandler(object sender, EventArgs e)[1] 的快捷方式。每当您在 C# 中使用签名时,您总是知道需要在正确的位置或作为参数编写什么,以便连接/调用某些对象/方法/等等。
- 定义事件后,您需要订阅以便在发生任何事情时得到通知。订阅事件的语法是 +=。退订自然是 -=。 MSDN 说语法应该是
object.event += eventHandler(或object.event += new EventHandler(eventHandler);)
- 所以在定义了一个事件(
event Event SomeEvent;)之后,剩下的就是创建一个可以绑定到这个事件的方法。此方法必须具有与 EventHandler 相同的签名,因此它应该与 [1] 的签名匹配,并且可以类似于 private void numberChangedEventHandler(object sender, EventArgs eventArguments)
现在您知道需要在 += 右侧写什么了。
一个例子:
public class NumberSequence
{
// numbers to be compared
private readonly List<int> numbers = new List<int>();
// used to generate a random collection
private readonly Random random = new Random();
// tell me if the previous and next number are different
public event EventHandler DifferentNumbersEvent;
public NumberSequence()
{
// fill the list with random numbers
Enumerable.Range(1, 100).ToList().ForEach(number =>
{
numbers.Add(random.Next(1, 100));
});
}
public List<int> Numbers { get { return numbers; } }
public void TraverseList()
{
for (var i = 1; i < this.numbers.Count; i++)
{
if (this.numbers[i - 1] != this.numbers[i])
{
if (this.DifferentNumbersEvent != null)
{
// whoever listens - inform him
this.DifferentNumbersEvent(this, EventArgs.Empty);
}
}
}
}
}
现在在使用类之前,定义事件处理程序,它将监听并在事件触发时被调用(再次措辞):
private void differentNumberEventHandler(Object sender, EventArgs eventArguments)
{
Console.WriteLine("Different numbers...");
}
及用法:
var ns = new NumberSequence();
ns.DifferentNumbersEvent += differentNumberEventHandler;
ns.TraverseList();
对于这种表示法(lambda / 匿名方法 / ...),其他一切都只是 syntactic sugar,例如:
object.Event += (s, e) => { // code ... }; 与object.Event += (Object sender, EventArgs eventArguments) => { // code ... }; 相同。你认得签名吗? - 与private void differentNumberEventHandler...相同。
通常我们需要通过事件传递信息,在这种情况下我们可能希望看到这两个数字。 C# 允许您使用自定义事件参数轻松完成此操作。只需创建一个继承 EventArgs 类的类并为应该传递的数据添加属性,在本例中为数字:
public class NumbersInfoEventArgs : EventArgs
{
public int Number1 { get; set; }
public int Number2 { get; set; }
}
然后在声明事件时指定它将传递NumbersInfoEventArgs 类型的数据(再次签名):
public event EventHandler<NumbersInfoEventArgs> DifferentNumbersEvent;
...
this.DifferentNumbersEvent(this, new NumbersInfoEventArgs
{
Number1 = this.numbers[i - 1],
Number2 = this.numbers[i]
});
最后但现在最重要的是,事件处理程序的签名应该与事件的签名匹配:
private void differentNumberEventHandler(Object sender, NumbersInfoEventArgs eventArguments)
{
Console.WriteLine("Different numbers {0} - {1}", eventArguments.Number1, eventArguments.Number2);
}
瞧,输出是:
Different numbers 89 - 86
Different numbers 86 - 53
Different numbers 53 - 12
Different numbers 12 - 69