黑马程序员:C#基础篇(三)委托与事件
来源:互联网 发布:arm linux gcc 安装 编辑:程序博客网 时间:2024/05/01 07:44
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
委托与事件
1、委托
委托是一种引用方法的类型,委托类型派生自.NET Framework 中的Delegate类,它是密封的,不能从Delegate中派生委托类型,也不能从中派生自定义类型。与委托的签名(由返回类型和参数构成)匹配的任何方法都可以分配给委托,这样既可通过编程的方式来更改方法的调用,也可以实现在现有类中插入代码(既通过委托传递方法)。
delegate void EventHandler(object sender,EventArgs e)
委托具有以下特点:
(1)类型安全
(2)允许将方法当做参数传递
(3)可用于定义回调方法
(4)可以链接在一起(可以对一个事件调用多个方法)
(5)方法不需要与委托签名精准匹配
说到委托,不得不说匿名方法,委托提供运算符和方法来添加或者删除目标方法,可以广泛地应用于事件、回掉、异步调用、多线程等,然而有时候仅仅为了使用一个委托,不得不创建一个类或方法,这个时候就可以用到匿名方法。
class SomeClass { delegate void SomeDelegate(); public void Fun() { SomeDelegate del = delegate() { Console.WriteLine("我是一个匿名方法,通过委托调用"); }; } }匿名方法被定义为内嵌方法,而不是作为任何类的成员,此外无法将方法属性应用到匿名方法,且匿名方法也不能定义一般类型或添加一般约束。如果匿名方法需要参数,则方法签名必须与其指派的委托定义相匹配,如同一个正常方法,例子:
class SomeClass { delegate void SomeDelegate(string str); public void Fun() { SomeDelegate del = delegate(string str) { Console.WriteLine("我是一个匿名方法,传入了一个参数 "+str); }; } }匿名方法还可以直接当作参数传递(委托允许将方法当作参数传递,这个方法可以是匿名方法),例子:
class MyClass { public void MyThread() { Thread NewThread = new Thread(delegate() { Console.WriteLine("把方法当作参数传递,开启新线程"); }); } }如果忽略delegate关键字后面的空括号,则定义一种特殊的匿名方法,他可以指派给任何委托,不管该委托是什么签名。 例子:
class MyClass { delegate void SomeDelegate(string str); delegate void SomeDelegate(); public void Fun() { SomeDelegate del1 = delegate { Console.WriteLine("delegate关键字后不加括号,则我可以指派给任何委托"); }; SomeDelegate del2 = delegate { Console.WriteLine("delegate关键字后不加括号,则我可以指派给任何委托"); }; } }注意一点,委托类型名字可以一样(只要签名不同就不算同一个委托)。
委托还可以定义一般参数”如同泛型“,例子:
class SomeClass<T> { delegate void SomeDelegate<T>(T t); public void Func(T t) { SomeDelegate<int> del = delegate(int num) { Console.WriteLine(num); }; del(123); } }
委托推理:
当将一个方法名指派给委托时,编译器首先推理该委托的类型,然后根据方法名检验他们的签名是否一致,然后会创建这个类型的实例,并把方法添加进调用列表。所以可以直接指派方法名给委托,而不必new一个委托对象,编译器自动为我们做了这些事。
class Class1 { delegate void SomeDelegate(ref int i); public static void Func(ref int i) { if (i <= 0) return; for (int j = 0; j < i; j++) { SomeDelegate del = Func; Console.WriteLine(i); i--; del(ref i); } } static void Main(string[] args) { int num = 5; Func(ref num); Console.ReadKey(); } }
委托还可以传递方法来回调,如窗体的通信例子:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private string str;//主窗体的私有字段 private void Func(string str)//主窗体的私有方法,等下会在新窗体中回调; { MessageBox.Show(str); } private void button1_Click(object sender, EventArgs e) { NewFrm frm = new NewFrm(); frm.str = this.str;//把主窗体的字段传递到新窗体 frm.Del = Func;//相当于授权(传递方法),授权给NewFrm对象的Del变量(委托变量) frm.Show(); } } //新窗体类 public partial class NewFrm : Form { public NewFrm() { InitializeComponent(); } public string str; delegate void SomeDelegate(string str); public SomeDelegate Del; private void button1_Click(object sender, EventArgs e) { if (Del != null) { Del(str); } } }
委托还可以实现多线程,例子:
class MyClass { static void Fun1() { for (int i = 0; i < 100000; i++) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(i); } } static void Fun2() { for (int i = 0; i < 10000; i++) { Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine(i); } } static void Fun3() { for (int i = 0; i < 10000; i++) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine(i); } } static void Main(string[] args) { //public Thread(ThreadStart start);这是Thread类定义的构造函数 //public delegate void ThreadStart();ThreadStart其实就是一个委托类型 Thread f1 = new Thread(Fun1); Thread f2 = new Thread(Fun2); Thread f3 = new Thread(Fun3); f1.Start(); f2.Start(); f3.Start(); } }
2、事件
事件是类在发生其关注的事情时用来提供通知的一种方式”这种通知称为引发事件,引发事件的对象称为事件源,通常可以作为参数传递给方法(当然还可以定义一些其他参数传递过去),事件使用委托来为触发时需要调用的方法提供类型安全的封装,当事件触发时,调用该委托,即调用绑定到委托的方法(事件其实就是委托变量)。例子:
public partial class MainFrm : Form //主窗体 { Form1 frm = new Form1();//Form1是主窗体的一个字段,相当于一个Button控件的样子 public MainFrm() { frm.Show(); InitializeComponent(); frm.MyEvent += this.Func;//绑定方法 } public void Func(string str) { MessageBox.Show(str); } } //为Form1添加了一个自定义事件 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private string str = "我是事件参数"; public delegate void MyDelegate(string str); public event MyDelegate MyEvent; private void button1_Click(object sender, EventArgs e) { if (MyEvent == null) return; MyEvent(str);//当调用button1_Click方法时触发该自定义事件(点击按钮时调用绑定到该事件的方法) } }可以看到,事件其实也是一种方法的传递。触发事件前应先判断是否订阅了事件,订阅事件其实就是绑定方法。在上例中MainFrm订阅了事件。
if (MyEvent == null) return;//其实就是判断该事件是否订阅了
还可以使用事件访问器声明事件(即添加、移除方法),例子:
delegate void TestEventDelegate(object o,EventArgs e); class EventSource { private TestEventDelegate TestEventHandlers; public event TestEventDelegate TestEvent { add { lock (TestEventHandlers) { TestEventHandlers += value; } } remove { lock (TestEventHandlers) { TestEventHandlers -= value; } } } private void RaiseTestEvent() { if (TestEventHandlers != null) { TestEventHandlers(this, new System.EventArgs()); } } }
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
- 黑马程序员:C#基础篇(三)委托与事件
- 黑马程序员--c#的委托与事件
- 黑马程序员--c#的委托与事件
- 黑马程序员--c#的委托与事件
- 黑马程序员--委托与事件
- 黑马程序员C#学习在路上--委托与事件
- C#基础系列--C#中委托与事件(三)
- C#基础-委托与事件
- [C#基础]委托与事件
- C#基础-委托与事件
- 黑马程序员--C#委托(使用委托)
- 黑马程序员---------委托与事件个人总结
- 黑马程序员--委托事件
- C#与C++的区别(三) 委托与事件
- C#委托与事件讲解(三)
- C#委托与事件讲解(三)
- C#委托与事件讲解(三)
- 黑马程序员-C#委托
- OpenCV矩阵运算
- 如何构建自己的SIP SERVER!
- wamp 403 禁止访问
- 美国项目管理:PMBOK第5版考试题
- NSIndexSet-入门浅析
- 黑马程序员:C#基础篇(三)委托与事件
- 详解sql_id,hash_value,address,old_hash_value
- 博弈总结
- 机械键盘到手
- Eclipse安装ADT Plugin时发生错误,提示连接不到 https://dl-ssl.google.com/android/eclipse/...的解决办法
- vsftpd 安装
- 通向架构师的道路(第二十七天)IBM网格计算与企业批处理任务架构
- Launching executable with NSTask - Sandboxing problems?
- jQuery对象与dom对象相互转换