委托
关于委托
delegate
关键字创建的类型就是 System.MuticastDelegate
(多播委托),使用反编译工具可以查看, System.MuticastDelegate
是保留类不允许继承。本质上委托都是多播委托,后期定义委托只有添加了多个方法才称为多播委托。
1
| public delegate void NoReturnNoParametersDelegate();
|
常见实例化方式
1 2 3 4 5 6
| NoReturnNoParametersDelegate delegate1 = new NoReturnNoParametersDelegate(DoNothing);
NoReturnNoParametersDelegate delegate2 = DoNothing;
NoReturnNoParametersDelegate delegate3 = () =>Console.WriteLine("This is a do nothing method.");
|
常见调用方式
1 2 3
| delegate1.Invoke(); delegate2(); delegate3.BeginInvoke(null, null);
|
委托的意义
逻辑和行为作为参数来传递
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| public T ExcuteSql<T>(string sql, Func<IDbCommand, T> func) { using(SqlConnection conn = new SqlConnection("")) { conn.Open(); IDbCommand cmd = conn.CreateCommand(); cmd.CommandText = sql; cmd.CommandType = CommandType.Text; return func(cmd); } }
Func<IDbCommand, Student> func = (cmd) => { IDataReader reader = cmd.ExecuteReader(); Student student = null; if(reader.Read()) { student = new Student(); } return student; }; Student student = ExcuteSql<Student>("select top 1 * from [Student]", func);
public static void SafeInvoke(Action act) { try { act.Invoke(); } catch(Exception exc) { Console.WriteLine(exc.Message); } }
SafeInvoke(() => ExcuteSql<Student>("select top 1 * from [Student]", func));
|
多播委托
+=
就是在委托的实例后面增加注册更多的方法,像一个链子,执行的时候按添加顺序执行
-=
就是在委托的实例后面移除注册的方法,从链子的尾部开始匹配,找到一个完全匹配的移除,没有不异常
1 2 3 4 5 6
| NoReturnNoParametersDelegate @delegate = DoNothing; @delegate += DoNothing; @delegate += DoNothing; @delegate += DoNothing; @delegate -= DoNothing; @delegate.Invoke();
|
观察者模式
1 2 3 4 5 6 7 8 9 10
| Action miaoAction = () => Console.WriteLine("Cat miao!"); miaoAction += () => Console.WriteLine("Mourse run!"); miaoAction += () => Console.WriteLine("Dog wang!"); miaoAction += () => Console.WriteLine("Baby cry!"); miaoAction += () => Console.WriteLine("Brother turn!"); miaoAction += () => Console.WriteLine("Mother whisper!"); miaoAction += () => Console.WriteLine("Father roar!"); miaoAction += () => Console.WriteLine("Neighbor awake!"); miaoAction += () => Console.WriteLine("Thief hide!");
|
事件
事件定义
委托的实例,加一个 event
关键字(一组方法)
使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public class EventTestClass { public event Action TestEvent; public void TestEventMethod() { Console.WriteLine("TestEventMethod invoke."); TestEvent?.Invoke(); } }
EventTestClass eventTest = new EventTestClass(); eventTest.TestEvent += () => Console.WriteLine("Cat miao!"); eventTest.TestEvent += () => Console.WriteLine("Mourse run!"); eventTest.TestEvent += () => Console.WriteLine("Dog wang!"); eventTest.TestEvent += () => Console.WriteLine("Baby cry!"); eventTest.TestEvent += () => Console.WriteLine("Brother turn!"); eventTest.TestEvent += () => Console.WriteLine("Mother whisper!"); eventTest.TestEvent += () => Console.WriteLine("Father roar!"); eventTest.TestEvent += () => Console.WriteLine("Neighbor awake!"); eventTest.TestEvent += () => Console.WriteLine("Thief hide!");
eventTest.TestEventMethod();
|
事件与委托的关系
委托是一种类型,事件是委托的一个实例。
event
关键字限制了权限,保证安全。
事件只能由发布者调用,外部不能调用也不能赋值,但是可以使用 +=
和 -=
向事件注册方法。
这个流程可以理解为解耦
1 2 3 4
| graph LR A(发布者)-->|动作| B(订户A) A-->|动作| C(订户B) A-->|动作| D(订户C)
|