C#之委托

关于委托的学习笔记

  1. 委托是一种类,类是数据类型,所以委托也是数据类型
//Action是一种类
Type t = typeof(Action);
Console.Write(t.IsClass);
  1. 委托是函数指针的升级版
    函数指针(C++):
#include <stdio.h>

//一个指向有两个参数和一个返回值的函数的指针
//这个指针只可以指向有两个int类型参数和一个int类型返回值的函数
//typedef 的作用在于,将这个指针定义为一种数据类型
//Calc 是给这个函数指针起的名称
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;

	//声明函数指针类型的变量
	//将Add函数的地址赋值给这个变量
	Calc calc = &Add;
	
	//1. 直接调用Add函数
	z = Add(x,y);
	printf("%d+%d=%d",x,y,z);

	//2. 通过函数指针,间接调用Add函数
	z = calc(x,y);
	printf("%d+%d=%d",x,y,z);
	
	//使控制台等待输入回车,便于观察控制台输出的结果
	system("pause");
}
  1. C#中比较常见的两种委托类型
    3.1 Action
    一般用于指向没有返回值的方法
class Student
{
	static void Main(string[] args)
	{
		//声明一个Action的变量,并创建一个实例
		//这个实例指向的是一个没有参数和返回值的方法PrintInf
		Action act = new Action(PrintInf);
		
		//1. 直接调用方法
		PrintInf();

		//2. 使用委托间接调用方法
		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类型返回值的方法Add
		//前面两个int代表了方法具有的参数
		//第三个int代表这个方法的返回值类型
		Func<int,int,int> func = new Func<int,int,int>(Add);  
		
		int i = 100int j = 100int z = 0;
		//1. 直接调用方法
		z = Add(i,j);

		//2. 使用委托间接调用方法
		z = func.Invork(i,j);
		//简便写法,模仿函数指针的书写格式
		z = func(i,j);
	}
	
	public int Add(int x,int y)
	{
		return  x + y;
	}
}
  1. 自定义委托
    委托是一种类,那么在自定义委托时,要把定义语句写在命名空间体内,如果写在类中,就变成了这个类的嵌套类了
namespace Study
{
	//自定义一个委托,需要使用关键字:delegate
	//这个委托指向一个具有两个int类型参数、返回值为int类型的方法
	public delegate int Calc(int,int);

	class Student
	{
		static void Main(string[] args)
		{
			//创建委托的变量和实例
			//在创建实例时,这个实例的构造函数要求指向一个具有两个int类型参数、返回值为int类型的方法
			Calc calc = new Calc(Add);
			
			int i = 100;
			int j = 100;
			int z = 0;
			
			//1. 直接调用Add方法
			z = Add(i,j);
			
			//2. 间接调用Add方法
			z = calc.Invork(i,j);
			//简便写法,模仿函数指针的书写格式
			z = calc(i,j);
		}
		
		int Add(int x, int y)
		{
			return x + y;
		}
	}
}
  1. 委托的一般使用
    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 + "是一个单数.");
}
  1. 委托的高级使用
    6.1 多播委托:一个委托指向多个方法
static void Main(string[] args)
{
	Action act1 = new Action(PrintInf);
	Action act2 = new Action(PrintInf);
	Action act2 = new Action(PrintInf);

	//将act2加到act1上;
	act1 += act2;
	//将act3加到act1上;
	act1 += act3;

	//只执行act1,这三个委托都会依次执行
	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()方法,我们实现了多线程异步调用,而实现多线程异步调用这一步骤的具体操作,是由编译器来实现的,并不是我们手动的创建多线程去实现的,所以称之为"隐式异步调用"。而多线程显示异步调用,也就是由我们直接手动创建多线程异步调用。

  1. 前面说到,我们C#的委托是C语言的函数指针的升级版,Java语言考虑安全问题,并不具有"指针"这一功能,那么在Java中,怎么实现委托的功能呢。
    那就是interface,Java完全使用接口代替了委托,所以在C#中,我们也可以在不适合使用委托时,使用接口来代替委托。
    7.1 委托的一些缺点:
    · 高耦合,委托属于方法级别的耦合;
    · 使代码可读性下降,增加debug难度;
    · 使用不当可能造成内存泄漏,让程序性能下降:
    当委托里封装着一个类的方法时,即使没有引用变量引用这个类,在内存中也会给这个类分配内容空间,从而造成内存泄漏,以及程序性能下降;
    · 等;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值