1.什么是委托?
委托可以把一个方法代入另一个方法,相当于指向函数的指针,换句话说,委托相当于一个函数指针,而事件就相当于保存委托的数组。
总的来说,委托是一个类,该类内部维护着一个字段,指向一个方法。
委托的声明:public delegate void DoDelegate();
通过委托执行方法
namespace ConsoleAppCSharp { class Program { static void Main(string[] args) {
DelegateExample delegateExample = new DelegateExample(); delegateExample.
DoFunction(); } } class DelegateExample { public delegate void DoDelegate(string
valueStr); internal void DoFunction() { //声明一个委托变量,并把已知方法作为构造函数的参数 DoDelegate
doDelegate= new DoDelegate(Test); //通过委托的静态方法Invoke触发委托 doDelegate?.Invoke(
"传入委托的值!"); } void Test(string valueStr) { Console.Write($"valueStr={valueStr}")
; } } }
1.在CLR运行时,DoDelegate实际上是一个类,该类的构造函数有一个参数类型,这个参数类型就是Test方法,并且提供了一个实例Invoke方法,用来触发委托执行;
2.委托DoDelegate定义了方法的参数和返回值类型;
3.通过委托DoDelegate的构造函数,可以将符合的方法赋值给委托;
4.调用委托的实例方法Invoke执行方法。
委托执行方法的另外一种方式:委托变量(参数列表)
namespace ConsoleAppCSharp { class Program { static void Main(string[] args) {
DelegateExample delegateExample = new DelegateExample(); delegateExample.
DoFunction(); } } class DelegateExample { public delegate void DoDelegate(object
sender, EventArgs e); internal void DoFunction() { //声明一个委托变量,并将已知方法作为构造函数的参数
DoDelegate doDelegate = new DoDelegate(Test); object sender = 888; EventArgs e =
new EventArgs(); doDelegate(sender, e); } void Test(object sender, EventArgs e)
{ Console.Write($"valueStr={sender}"); } } }
1.委托DoDelegate的参数列表和Test方法的参数列表保持一致;
2.委托DoDelegate中的参数object sender通常表示动作的发起者,EventArgs e表示动作所带的参数。
实际上,事件就是采用委托变量(参数列表)形式执行方法。
2.什么是事件?
事件是基于委托的,为委托提供一个订阅或发布的机制。事件是一种特殊的委托,调用事件和委托是一样的。
事件可以被看作是委托类型的一个变量,通过事件注册、取消多个委托和方法。
事件的声明:
public event 委托类型 事件名称;
如:public event DoDelegate DoEvent;
通过事件执行方法
namespace ConsoleAppCSharp { class Program { static void Main(string[] args) {
DelegateExample delegateExample = new DelegateExample(); delegateExample.
DoFunction(); } } class DelegateExample { public delegate void DoDelegate(object
sender, EventArgs e); public event DoDelegate DoEvent; internal void DoFunction
() { //声明一个委托变量,并将已知方法作为构造函数的参数 DoDelegate doDelegate = new DoDelegate(Test);
object sender = 888; EventArgs e = new EventArgs(); DoEvent += new DoDelegate(
doDelegate); DoEvent(sender, e); } void Test(object sender, EventArgs e) {
Console.Write($"valueStr={sender}"); } }
1.声明事件DoEvent,事件的类型是DoDelegate委托;
2.通过+=为事件注册委托;
3.通过DoDelegate的构造函数为事件注册委托实例;
4.采用委托变量(参数列表)形式,然事件执行方法。
通过+=还可以为事件注册多个委托
namespace ConsoleAppCSharp { class Program { static void Main(string[] args) {
DelegateExample delegateExample = new DelegateExample(); delegateExample.
DoFunction(); } } class DelegateExample { public delegate void DoDelegate(object
sender, EventArgs e); public event DoDelegate DoEvent; internal void DoFunction
() { //声明一个委托变量,并将已知方法作为构造函数的参数 DoDelegate doDelegate = new DoDelegate(Test);
DoDelegate doDe = new DoDelegate(TestExample); object sender = 888; EventArgs e
= new EventArgs(); //事件注册多个委托 DoEvent += new DoDelegate(doDelegate); DoEvent +=
new DoDelegate(doDe); DoEvent(sender, e); } void Test(object sender, EventArgs e
) { Console.Write($"valueStr={sender}"); } void TestExample(object sender,
EventArgs e) { Console.Write($"valueStr={sender}"); } }
通过+=为事件注册一个或多个委托实例,实际上还可以为事件直接注册方法。
事件直接注册方法
namespace ConsoleAppCSharp { class Program { static void Main(string[] args) {
DelegateExample delegateExample = new DelegateExample(); delegateExample.
DoFunction(); } } class DelegateExample { public delegate void DoDelagate(object
sender, EventArgs e); public event DoDelagate DoEvent; internal void DoFunction
() { object sender = 888; EventArgs e = new EventArgs(); //为事件注册多个委托 DoEvent +=
Test; DoEvent += TestExample; DoEvent(sender, e); } void Test(object sender,
EventArgs e) { Console.Write($"valueStr={sender}"); } void TestExample(object
sender, EventArgs e) { Console.Write($"valueStr={sender}"); } }
通过EventHandler执行方法
EventHandler的源码:public delegate void EventHandler(object sender, EventArgs e);
从源码中可以看出,EventHandler是一个委托。使用EventHandler来执行多个方法。
namespace ConsoleAppCSharp { class Program { static void Main(string[] args) {
DelegateExample delegateExample = new DelegateExample(); delegateExample.
DoFunction(); } } class DelegateExample { public event EventHandler DoEvent;
internal void DoFunction() { object sender = 888; EventArgs e = new EventArgs();
//为事件注册多个委托 DoEvent += Test; DoEvent += TestExample; DoEvent(sender, e); } void
Test(object sender, EventArgs e) { Console.Write($"valueStr={sender}"); } void
TestExample(object sender, EventArgs e) { Console.Write($"valueStr={sender}"); }
}
总的来说:
1.委托是一个类,可以实例化,通过委托的构造函数把方法赋值给委托实例;
2.触发委托有两种方式:委托实例.Invoke(参数列表)和委托实例(参数列表);
3.事件可看作是一个委托类型的变量;
4.+=为事件注册多个委托实例或多个方法;
5.-=为事件减少多个委托实例或多个方法;
5.EventHandler是一个委托。
3.委托与实例的区别
1.事件只能在方法的外部进行声明,而委托在方法的外部和内部都可以进行声明;
2.事件只能在类的内部进行触发,不能在类的外部进行触发。而委托在类的内部和外部都可触发;
3.委托一般用于回调,而事件一般用于外部接口。在观察者模式中,被观察者可在内部声明一个事件作为外部观察者注册的接口。