关于委托的学习笔记
- 委托是一种类,类是数据类型,所以委托也是数据类型
Type t = typeof(Action);
Console.Write(t.IsClass);
- 委托是函数指针的升级版
函数指针(C++):
#include <stdio.h>
typedef int(*Calc)(int a,int b);
int Add(int a,int b){
int result = a + b;
return result;
}
int main(){
int x = 100;
int y = 100;
int z = 0;
Calc calc = &Add;
z = Add(x,y);
printf("%d+%d=%d",x,y,z);
z = calc(x,y);
printf("%d+%d=%d",x,y,z);
system("pause");
}
- C#中比较常见的两种委托类型
3.1 Action 一般用于指向没有返回值的方法
class Student
{
static void Main(string[] args)
{
Action act = new Action(PrintInf);
PrintInf();
act.Invork();
act();
}
public void PrintInf()
{
Console.WriteLine("My Name is Wednesday.");
}
}
3.2 Func 一般用于指向有返回值的方法
class Student
{
static void Main(string[] args)
{
Func<int,int,int> func = new Func<int,int,int>(Add);
int i = 100;
int j = 100;
int z = 0;
z = Add(i,j);
z = func.Invork(i,j);
z = func(i,j);
}
public int Add(int x,int y)
{
return x + y;
}
}
- 自定义委托
委托是一种类,那么在自定义委托时,要把定义语句写在命名空间体内,如果写在类中,就变成了这个类的嵌套类了
namespace Study
{
public delegate int Calc(int,int);
class Student
{
static void Main(string[] args)
{
Calc calc = new Calc(Add);
int i = 100;
int j = 100;
int z = 0;
z = Add(i,j);
z = calc.Invork(i,j);
z = calc(i,j);
}
int Add(int x, int y)
{
return x + y;
}
}
}
- 委托的一般使用
5.1 模板方法 · 在方法中,根据委托所指向的方法返回的数据,来进行记算。 · 委托有返回值
static void Main(string[] args)
{
int x = 100;
int y = 100;
int z = 0;
Func<int,int,int> act = new Func<int,int,int>(Add);
z = 100 + act.Invork(x,y);
}
int GetNum(int x, int y)
{
return x + y;
}
5.2 回调方法 · 由主调方法决定是否调用被调方法 · 委托无返回值
static void Main(string[] args)
{
int x = 2;
int y = 3;
Action<int> act = new Action<int>(PrintInf);
if(x % 2 != 0)
act.Invork(x);
if(y % 2 != 0)
act.Invork(y);
}
void PrintInf(int x)
{
Console.WriteLine(x + "是一个单数.");
}
- 委托的高级使用
6.1 多播委托:一个委托指向多个方法
static void Main(string[] args)
{
Action act1 = new Action(PrintInf);
Action act2 = new Action(PrintInf);
Action act2 = new Action(PrintInf);
act1 += act2;
act1 += act3;
act1.Invork();
}
void PrintInf()
{
Console.WriteLine("My name is Wednesday.");
}
6.2 隐式异步调用 多播委托的例子为同步调用,异步调用则是指多线程并行调用
· 使用多线程显示异步调用
static void Main(string[] args)
{
Thread thread1 = new Thread(new ThreadStart(PrintInf));
Thread thread2 = new Thread(new ThreadStart(PrintInf));
Thread thread3 = new Thread(new ThreadStart(PrintInf));
thread1.Start();
thread2.Start();
thread3.Start();
}
void PrintInf()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("My name is Wednesday,I'm {0} years old", i);
Thread.Sleep(1000);
}
}
运行结果:每条线程并发执行 · 使用委托隐式异步调用:
static void Main(string[] args)
{
Action act1 = new Action(PrintInf);
Action act2 = new Action(PrintInf);
Action act3 = new Action(PrintInf);
act1.BeginInvoke(null,null);
act2.BeginInvoke(null,null);
act3.BeginInvoke(null,null);
}
void PrintInf()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("My name is Wednesday,I'm {0} years old", i);
Thread.Sleep(1000);
}
}
运行结果:
使用委托隐式异步调用,和使用多线程显示异步调用,结果都是一样的,那么隐式和显示的区别是什么? 这里说的隐式异步调用全称应该是:多线程隐式异步调用。 也就是说,通过委托的BeginInvoke()方法,我们实现了多线程异步调用,而实现多线程异步调用这一步骤的具体操作,是由编译器来实现的,并不是我们手动的创建多线程去实现的,所以称之为"隐式异步调用"。而多线程显示异步调用,也就是由我们直接手动创建多线程异步调用。
- 前面说到,我们C#的委托是C语言的函数指针的升级版,Java语言考虑安全问题,并不具有"指针"这一功能,那么在Java中,怎么实现委托的功能呢。
那就是interface,Java完全使用接口代替了委托,所以在C#中,我们也可以在不适合使用委托时,使用接口来代替委托。 7.1 委托的一些缺点: · 高耦合,委托属于方法级别的耦合; · 使代码可读性下降,增加debug难度; · 使用不当可能造成内存泄漏,让程序性能下降: 当委托里封装着一个类的方法时,即使没有引用变量引用这个类,在内存中也会给这个类分配内容空间,从而造成内存泄漏,以及程序性能下降; · 等;
|