委托在底层就是一个函数的指针,委托是事件的基础。
你可以传递引用类型、值类型、但是你有没有需要传一个方法呢?传方法的过程就是委托。
消息类:
public class Message { /// <summary> /// 传引用类型 /// </summary> /// <param name="msg"></param> public static void Send(string msg) { Console.WriteLine("你传递的参数是string:{0}", msg); } /// <summary> /// 传值类型 /// </summary> /// <param name="msg"></param> public static void Send(int msg) { Console.WriteLine("你传递的参数是int:{0}", msg); } /// <summary> /// 利用委托传一个方法过来 /// </summary> /// <param name="msg"></param> public static void Send(Action msg) { ///执行它 msg.Invoke(); // Console.WriteLine("你传递的参数是int:{0}", msg); } }
使用例子:
class Program { static void Main(string[] args) { ///传引用类型的字符串 Message.Send("晚上好!端午节快乐!"); ///传值类型的,int 68 Message.Send(68); ///传一个方法 Message.Send(SendMessage); Console.ReadKey(); } /// <summary> /// 方法 /// </summary> static void SendMessage() { Console.WriteLine("我是 Program 类的 SendMessage 方法"); } }
运行结果:
是不是很有用处:
当两个对象之间的处理结果需要相互通知。(onClick,onLoad等一切的事件,基础都是基于委托),委托实际就是一个观察者模式。其作用是两个对象之间可以通过委托,相互通知消息。
委托的定义:
public class DelegateExample { /// <summary> /// 定义一个方法,方法有0到N个参数,可以有返回值,和无返回值 /// </summary> /// <param name="msg"></param> public void MethodTest(int Ivalue) { } /// <summary> /// 定义另一个委托,委托和方法一样有0到N个参数,可以有返回值,和无返回值 /// </summary> /// <param name="msg"></param> /// <param name="msg2"></param> public delegate int DelegateTest(string msg, string msg2); public void Show() { ///定义委托:委托像 “类” 一样,定义来使用,用 new DelegateTest 来指向方法 DelegateTest delegateTest1 = new DelegateTest(DelegateTest2_Mothod); ///调用委托:将参数给定 delegateTest1.Invoke("aa", "bb"); Console.WriteLine("------------------------------------"); ///直接指向方法 DelegateTest delegateTest2 = DelegateTest2_Mothod; ///不用 Invoke 也可以直接使用 delegateTest1("cc", "dd"); Console.WriteLine("------------------------------------"); ///用 Lambda 表达式来定义一个匿名方法 DelegateTest delegateTest3 = (string msg, string msg2) => { Console.WriteLine("BeginInvoke"); return msg.Length + msg2.Length; }; ///异步来调用 delegateTest3.BeginInvoke("ee", "ff", null, null); Console.WriteLine("------------------------------------"); ///用 Lambda 表达式来定义一个匿名方法 DelegateTest delegateTest4 = (string msg, string msg2) => { Console.WriteLine("执行委托"); return msg.Length + msg2.Length; }; ///多次指定方法(多播委托) delegateTest4 += (string msg, string msg2) => { Console.WriteLine("执行委托"); return msg.Length + msg2.Length; }; delegateTest4 += DelegateTest2_Mothod; delegateTest4 += DelegateTest2_Mothod; ///减掉一个 delegateTest4 -= DelegateTest2_Mothod; ///减掉一个匿名委托,实际是不起作用的,因为匿名没有“固定”指向名称,所以不能减掉,下面同样会执行 delegateTest4 -= (string msg, string msg2) => { Console.WriteLine("执行委托"); return msg.Length + msg2.Length; }; delegateTest4.Invoke("dd", "eee"); } int DelegateTest2_Mothod(string msg, string msg2) { Console.WriteLine("执行委托"); return msg.Length + msg2.Length; } }
执行结果是:
delegateTest1 直接用(delegateTest1("cc", "dd");),Invoke调用,delegateTest1.Invoke("aa", "bb");两次结果完全相同
delegateTest3 begininvoke 是在前面的,结果跑到最后面。异步的原因。
delegateTest4 加了4次委托,减掉2次,但是执行3次,说明了有一次没有减掉。就是匿名没有减掉。
记住委托的作用就是,定义一个方法(函数)的指针。
在编程中,委托是一个非常有用的功能,因为任何异步调用的基础也是委托
.net 框架为我们定义好了两个委托,一个有返回值,一个无返回值,这样我们就免于需要创建委托的重复劳动:
无返回
Action
Action<string>
0-16个参数,无返回值
在系统当中大量使用
有返回
func<int>
fun<string,int> 第一个是参数,最后是返回值
1-17,前面是参数,最后一个是返回值
在系统当中大量使用
1、异步必须要用委托
2、方法像类型一样传递,可以分离业务逻辑
事件的基础就是委托:
事件在系统中使用的非常之多。
定义一个事件:
/// <summary> /// 定义一个事件 /// </summary> public event Action<string> SendEvent;
事件的使用:
static void Main(string[] args) { ///传引用类型的字符串 Message.Send("晚上好!端午节快乐!"); ///传值类型的,int 68 Message.Send(68); ///传一个方法 Message.Send(SendMessage); DelegateExample delegateExample = new DelegateExample(); delegateExample.Show(); ///实例化事件类 MyEvent myevent = new MyEvent(); ///订阅事件 myevent.SendEvent += Myevent_SendEvent; ///执行工作 myevent.Send(string.Format("开始:{0}", DateTime.Now)); Console.ReadKey(); } /// <summary> /// 订阅的处理方法(确定委托需要指针,指向的方法) /// </summary> /// <param name="obj"></param> private static void Myevent_SendEvent(string obj) { Console.WriteLine("返回:{0}", obj); }
事件演示代码:
public class MyEvent { /// <summary> /// 方法的定义 /// </summary> /// <param name="msg"></param> public void MethodDemo(string msg) { } /// <summary> /// 委托的定义,委托在方法修饰符后面加 delegate /// 委托没有实体{} /// </summary> /// <param name="msg"></param> public delegate void delegateDemo(string msg); /// <summary> /// 事件的定义,事件在委托修饰符后面加 event /// </summary> public event delegateDemo eventDemo; /// <summary> /// /// 记住,事件必须以一个委托为基础 /// 定义一个事件,本例中以系统自带的 Action 为基础 /// /// </summary> public event Action<string> SendEvent; public void Send(string msg) { Task.Factory.StartNew(() => { Thread.Sleep(TimeSpan.FromSeconds(15)); ///在 if (SendEvent != null) { SendEvent(string.Format("Task.Factory.StartNew:{0},{1}", DateTime.Now, msg)); } }); } }
运行结果:
委托是一种类型、是一个函数指针、事件就是委托的一个实例
委托加上一个 EVENT 关键字后就变成了事件
事件不能直接赋值。也不能被调用。只能通过+=,-= 来操作委托
委托就是 观察者模式 的实现方法
委托是业务之间逻辑剥离的解决方案。