>无扰阅读模式(测试) 先报一下现况吧:目前正在做WPF版的Walkman Playlist Tools,增加和完善了很多功能,小小地图透一下: 具体改了什么功能,先卖个关子。 这么长时间没更真的没有在摸鱼哦!真的没有! 那么,我们步入正题吧:
委托
[delegate]
委托?
简单地说,委托的实质是函数的指针。
实现委托?
和其他类型一样,委托在实现之前也要先定义类,这个类称为委托,而委托函数的是委托的成员(可以看作委托类的对象)。
①Action委托
前面说过,委托在实现之前必先定义类,这个类可以自己定义(之后会讲),也可以直接使用系统定义好的委托类,这里讲的Action
和下面的Func
就是这样的类。 Action
委托是可添加无传入值,且无返回值(void
)方法的委托类。
创建:
1 | Action anyname =new Action( FunctionHere ); |
调用(以下三条代码效果相同):
1 | anyname.Invoke();//调用委托(完全版) |
②Func委托
Func委托是通过泛型容纳任何一种函数的委托类。
创建:
1 | Func<Type1,Type2,...ReturnType> anyname=new Func<Type1,Type2,...ReturnType>( FunctionHere ) |
如上,泛型中可填入任意数量的数据类型,其中最后一个输入的数据类型用作规定函数的返回类型,其他(除了最后一个)数据类型可以规定函数的传入类型。需要注意的是,若只填入一个类型,那么这个类型是函数的返回类型。
调用:
1 | anyname.Invoke();//调用委托(完全版) |
③委托的声明(自定义委托)
委托的声明方式与一般类不同,主要是为了照顾可读性和C、C++传统。 注意声明委托的位置,避免写错地方结果声明成嵌套类型。 委托所封装的方法必须类型兼容。
定义:
1 | public delegate double Calc(doule x,double y); |
调用:
1 | calc1.Invoke((double)var,(double)var);//调用委托(完全版) |
④委托的使用
——当作数据传入函数
- 用作模板(常位于代码中部,有返回值)
- 回调方法(常位于代码尾部,无返回值,多用于执行后续操作)
注意:难精通、易使用、功能性强的功能一旦滥用后果非常严重 1. 这是一种方法级别的紧耦合,现实工作中使用应慎之又慎 1. 可使得程序可读性下降,doubug难度增加 1. 把委托回调、异步调用和多线程纠缠在一起,会让代码变得难以阅读和维护 1. 使用不当可能造成内存泄漏和程序性能下降
⑤多播委托
刚刚演示的委托均为单播委托,即一个委托只有一个方法相应。由此推广,多播委托即为一个委托可有多个方法相应。
方法:
使用+=
可在委托的成员中再添加一个方法。
演示:
1 | Action action1=new Action(Function1); |
⑥异步调用
先明确几个称呼: 一个程序只有一个进程,但是可以有很多个线程。
同步=串行=单线程; 异步=并行=多线程;
- 直接同步调用:使用方法名
- 间接同步调用:使用单播/多播委托的
Invoke
方法 - 隐式异步调用:使用委托的
BeginInvoke
方法,如csharp anyname.BeginInvoke(delegate,object) //第一个传入值为委托类型,标明该线程做完后做什么,什么都不做就填null //第二个传入值默认传入null
需要注意的是,这是相比主线程而分离的分支线程,也就是说使用n次BeginInvoke
就调用了 n+1个线程 - 显式异步调用: 1.Thread类:
1 | Using System.Threading; |
2.Task类:
1 | Using System.Threading.Task; |
⑦用接口代替委托
Java的做法,降低耦合度,提高可读性