Skip to content
字数
1196 字
阅读时间
6 分钟

委托-delegate

声明委托 委托不存在函数的重载概念

cs
delegate void MyFun();
public delegate int MyFun2(int a);
//委托支持泛型
delegate T MyFun3<T, K>(T v, K k);

NOTE

Action: 没有返回值,参数提供了 0~16 个委托给我们用 Func: 有返回值,参数提供了 0~16 个委托给我们用

cs
class Test
{
	public MyFun fun;
	public MyFun2 fun2;
	
	public Action action;
	
	public void TestFun(MyFun fun, MyFun2 fun2)
	{
		//委托最大的作用:先处理别的逻辑 处理完后再执行传入的函数
		int i = 1;
		i *= 2;
		
		//fun();
		//fun2(i)
		this.fun = fun();
		this. fun2 = fun2(2);
	}
	public void AddFun(MyFun fun, Myfun2 fun2)
	{
		this.fun += fun;
		this.fun2 += fun2;
	}
	public void RemoveFun(MyFun fun, MyFun2 fun2)
	{
		//this.fun = this.fun - fun;
		this.fun -= fun;
		this.fun2 -= fun2;
	}
}
class Program{
	static void Main(string[] args)
	{
		MyFun f = new MyFun(Fun);
		f.Invoke();
		
		MyFun f2 = Fun;
		f2();
		
		MyFun2 f3 = Fun2;
		Console.WriteLine(f3(1));

		MyFun2 f4 = new MyFun2(Fun2);
		Console.WriteLine(f4.Invoke(3));
		
		//用委托存储多个函数
		MyFun ff = Fun;
		ff += Fun;
		ff();//Fun会执行两次
		ff -= Fun;//多减不会报错
		ff();
		ff = null;
		//清空容器
		
		//使用自定义的委托
	 	Test t = new Test();
	  	t.TestFun(Fun, Fun2);
	  	
	  	//系统提供的委托Action 无返回值 引用using System;
	  	//统提供的委托 Func<> 有返回值
	  	Action action = Fun;
	  	action += Fun;
	  	action();
	  	
	  	Func<string> funcString = Fun4;
	  	Func<int> funcInt = Fun5;
	  	
	  	//系统提供1-16个参数的委托 有参无返回值
	  	Action<int, string> action2 = Fun6;
	  	//有参有返回值 前参数类型 后返回值类型
	  	Func<int, int> func2 = Fun7;
	}
	static void Fun()
	{
		Console.WriteLine("123123");
	}
	static void Fun2(int value)
	{
		return value;
	}
	static string Fun4()
	{
		return " ";
	}
	static int Fun5()
	{
		return 1;
	}
	static void Fun6(int a, string str)
	{
		Console.WriteLine(a + str);
	}
	static int Fun7(int value)
	{
		return value;
	}
}

事件-Event

事件是基于委托的存在,让委托的使用更具有安全。事件是特殊的委托。 申明语法: 访问修饰符 event 委托类型 事件名; 事件的使用:

  1. 事件是作为成员变量存在于类中
  2. 事件和委托的使用基本一模一样 事件相对于委托的区别:
  3. 不能在==类外部==赋值,但是可以 加减 去添加移除记录的函数
  4. 不能再==类外部==调用 注意:它只能作为成员存在于类和接口以及结构体中
cs
class Test
{
	public Action myFun;
	public event Action myEvent;
	public Test()
	{
		myFun = TestFun;
		//在类的内部,事件和委托的使用一模一样
		myEvent = TestFun;
		myEvent += TestFun;
		myEvent -= TestFun;
		myEvent();
		myEvent.Invoke();
		myEvent = null;
	}
	public void DoEvent()
	{
		if(myEvent != null)
		myEvent();
	}
	public void TestFun()
	{
		Console.WriteLine("123");
	}
}
class Program
{
	static void Main(string[] args)
	{
		Test t = new Test;
		//事件不能在类的内部调用,只能在类的内部去封装 调用
		t.DoEvent();
		//事件不能作为临时变量在函数中使用,委托可以作为临时变量
		//event Action ae = TestFun;报错
		Action a = TestFun;
	}
	static void TestFun(){}
}

匿名函数

配合委托和事件进行使用

cs
class Program
{
	static void Main(string[] args)
	{
		//无参无返回
		Action a = delegate()
		{
			Console.WriteLine("匿名函数逻辑");
		};
		a();//调用匿名函数
		//有参
		Action<int, string> b = delegate(int a, string b)
		{
			Console.WriteLine(a);
			Console.WriteLine(b);
		};
		b(100, "123");
		//有返回值
		Func<string> c = delegate()
		{
			return "123123";
		};
		//匿名函数 一般作为函数参数传递 或作为函数返回值
		Test t = new Test();
		//参数传递
		t.Dosomthing(100, delegate(){
			Console.WriteLine("随参数传入的匿名函数逻辑");
		});
		//返回值
		Action ac2 = t.GetFun();
		ac2();
		//一步到位 直接调用委托函数
		t.GetFun()();
	}
}
class Test
{
	public Action action;
	//作为参数传递时
	public void Dosomthing(int a, Action fun)
	{
		Console.WriteLine(a);
		fun();
	}
	//作为返回值时
	public Action GetFun()
	{
		return delegate(){
			Console.WriteLine("函数内部返回的匿名函数逻辑");
		};
	}
}

Lambad 表达式

可看作匿名函数的简写

cs
class Program
{
	static void Main(string[] args)
	{
		//无参
		Action a = () =>
		{
			Console.WriteLine("无参无返回值的lambad表达式");
		};
		a();
		//有参
		Action<int> a2 = (int value) =>
		{
			Console.WriteLine(value);
		};
		a2(100);
		//有参 省略参数类型
		Action<int> a3 = (value) =>
		{
			Console.WriteLine(value);
		};
		a3(200);
		//有返回值
		Func<string, int> a4 = (str) =>
		{
			Console.WriteLine("有参有返回值" + str);
			return 1;
		};
		Console.WriteLine(a4("123456"));
	}

}

闭包

内层的函数可以引用包含在它外层的函数的变量,即使外层函数的执行已经终止。 注意:该变量提供的值并非变量创建时的值,而是在父函数范围内的最终值

cs
class Test
{
	public event Action action;
	pulbic Test()
	{
		int value = 10;
		action = () =>
		{
			Console.WriteLine(value);//因为闭包,value的声明周期被改变
		};
		
		for(int i = 0; i < 10; i++)
		{
			action += () =>
			{
				Console.WriteLine(i);//输出都是10,因为i的最终值为10
			};
		}
		//如果想遍历
		for(int i = 0; i < 10; i++)
		{
			int index = i;//作为一个新临时变量
			action += () =>
			{
				Console.WriteLine(index);
			};
		}
	}
	public void Dosomthing()
	{
		action();
	}
}

贡献者

The avatar of contributor named as worldddddd worldddddd

文件历史

撰写