2019独角兽企业重金招聘Python工程师标准>>>
首先了解一下事件程序流程
- 定义事件参数类
- 定义委托类型
- 声明事件(发布事件者)
- 定义事件的订阅者类
- 定义 响应 事件的函数。 On开头的函数。(发布者中实现)
- 定义 调用 事件函数的 业务逻辑。 (发布者中实现)
定义事件参数类
这个类中,我们只定义了动物的叫声。
///
/// 事件
///
public class AnimalEventArgs : EventArgs
{
///
/// 叫声
///
public string wow;
///
/// 构造方法
///
/// 叫声
public AnimalEventArgs(string s)
{
this.wow = s;
}
}
定义委托类型
///
/// 事件的订阅者、事件的发布者
///
class Animals
{
///
/// 定义委托类型
///
/// 事件的发布者
/// 事件参数类
public delegate void WowEventHandler(object sender, AnimalEventArgs e);
}
声明事件
///
/// 事件的订阅者、事件的发布者
///
class Animals
{
///
/// 定义委托类型
///
/// 事件的发布者
/// 事件参数类
public delegate void WowEventHandler(object sender, AnimalEventArgs e);
///
/// 声明事件
///
public event WowEventHandler Wow;
}
构造方法中订阅事件
///
/// 事件的订阅者、事件的发布者
///
class Animals
{
///
/// 定义委托类型
///
/// 事件的发布者
/// 事件参数类
public delegate void WowEventHandler(object sender, AnimalEventArgs e);
///
/// 声明事件
///
public event WowEventHandler Wow;
///
/// 构造方法,事件绑定方法
///
public Animals()
{
Wow += this.WOW;
}
///
/// 响应事件的函数,事件的订阅方法
///
/// 事件的发布者
/// 事件参数类
public void WOW(Object sender, AnimalEventArgs e)
{
Console.WriteLine("Animal wow : {0}", e.wow);
}
}
定义 响应 事件的函数。 On开头的函数。(发布者中实现)
///
/// 事件的订阅者、事件的发布者
///
class Animals
{
///
/// 定义委托类型
///
/// 事件的发布者
/// 事件参数类
public delegate void WowEventHandler(object sender, AnimalEventArgs e);
///
/// 声明事件
///
public event WowEventHandler Wow;
///
/// 构造方法,事件绑定方法
///
public Animals()
{
Wow += this.WOW;
}
///
/// 响应事件的函数,事件的订阅方法
///
/// 事件的发布者
/// 事件参数类
public void WOW(Object sender, AnimalEventArgs e)
{
Console.WriteLine("Animal wow : {0}", e.wow);
}
///
/// 调用方法触发事件
///
/// 事件参数类
public virtual void OnWow(AnimalEventArgs e)
{
if (Wow != null)
Wow(this, e);
}
}
定义 调用 事件函数的 业务逻辑。 (发布者中实现)
class Program
{
static void Main(string[] args)
{
//初始化,也可以在Cat、Dog类的构造方法中初始化Animals
Animals animals = new Animals();
Cat cat = new Cat();
cat.animal = animals;
Dog dog = new Dog();
dog.animal = animals;
cat.AnimalWow();
dog.AnimalWow();
Console.ReadKey();
}
}
class Cat
{
public string wowStr = "喵喵";
public Animals animal;
///
/// 让动物叫
///
public void AnimalWow()
{
//事件参数类
AnimalEventArgs e = new AnimalEventArgs(wowStr);
animal.OnWow(e);
}
}
class Dog
{
public string wowStr = "旺旺";
public Animals animal;
public void AnimalWow()
{
AnimalEventArgs e = new AnimalEventArgs(wowStr);
animal.OnWow(e);
}
}
在下面方法中:
///
/// 调用方法触发事件
///
/// 事件参数类
public virtual void OnWow(AnimalEventArgs e)
{
if (Wow != null)
Wow(this, e);
}
这种做法是线程不安全的
if (Wow != null)
Wow(this, e);
下面是一种安全的做法
///
/// 调用方法触发事件
///
/// 事件参数类
public virtual void OnWow(AnimalEventArgs e)
{
//临时委托变量,防止多线程移除委托(CLR里提到这是线程不安全的做法,因为单我们判断不为空后,准备执行时,另一个线程将从委托链将委托移除,此时变成了空,引发NullReferenceException异常。)
WowEventHandler temp = this.Wow;
if (temp != null)
temp(this, e);
}
委托的本质是引用类型,用于包装回调函数,委托用于实现回调机制;事件的本质是委托,事件是回调机制的一种应用。