委托
定义
类似于C++中的函数指针,接收存储传递指定格式的函数并在指定时刻调用
基本语法
关键字:delegate
语法: 访问修饰符 delegate 返回值 委托名(参数列表);
写在哪里:
可以申明在namespace 和 class语句块中
更多的写在namespace中
自定义委托
访问修饰符一般不写,默认为public 这样在别的命名空间也能用
//无参无返回值函数的容器
delegate void MyFun();
//委托规则的申明 不能重名(同一语句块中)
//返回值为int 含一个int参数的函数容器
delegate int MyFun2(int a);
使用定义好的委托
class Test
{
public MyFun fun;
public MyFun2 fun2;
public void TestFun(MyFun fun,MyFun2 fun2)
{
//可以先处理别的逻辑,得到的结果作为参数传入fun2中
//延迟执行
//fun();
//fun2(i);
this.fun = fun;
this.fun2 = fun2;
}
}
internal class Program
{
static void Main(string[] args)
{
MyFun f = new MyFun(Fun);
f();
f.Invoke();
MyFun f2 = Fun;
f2();
f2.Invoke();
MyFun2 f3 = Fun2;
Console.WriteLine(f3(345));
Test t = new Test();
t.TestFun(Fun, Fun2);
}
static void Fun()
{
Console.WriteLine("123");
}
static int Fun2(int a)
{
return a;
}
}
委托可以存储多个函数(多播委托)
MyFun ff = Fun;
//不能直接MyFun ff += Fun;
//但是可以MyFun ff = null;后再ff+=Fun;
ff += Fun;
ff += Fun3;
ff();
public void AddFun(MyFun fun,MyFun2 fun2)
{
this.fun += fun;
this.fun2 += fun2;
}
t.AddFun(Fun, Fun2);
t.fun();
Console.WriteLine(t.fun2(50));//这里只会返回最后一个50并输出,原因下面再讲
删也同理
系统定义的委托
需要using System命名空间
//无参无返回值委托
Action action = Fun;
action += Fun3;
action();
//指定返回类型的泛型委托,无参
Func<string> funstring = Fun4;
Func<int> funint = Fun5;
//可以传n个参数的委托 系统提供了1-16个参数的委托 但是无返回值
Action<int, string> action2 = Fun6;
Console.ReadLine();
//可以传n个参数的委托 系统提供了1-16个参数的委托 但是有返回值 参数都在前面最后一个是返回值
Func<int, int> func2 = Fun2;
static void Fun3()
{
Console.WriteLine("33333");
}
static string Fun4()
{
return "string";
}
static int Fun5()
{
return 1;
}
static void Fun6(int i,string s)
{
}
补充:
事件
定义
事件可以理解成经过封装后的委托,他不能想委托一样直接在类外面调用或赋值
基本语法
访问修饰符 event 委托类型 事件名
使用
现有一Test类
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 TestFun()
{
Console.WriteLine("111");
}
public void DoEvent()
{
if(myEvent != null)
{
myEvent();
}
}
}
myFun可以在类的外部直接赋值、调用,例如用Invoke调用,用=赋值
而myEvent就不行,只允许在类内用一些函数来封装赋值和调用,但是+=和-=是可以用的
class Promgram
{
static void Main(string[] args)
{
Test t = new Test();
//委托可以在外部赋值
t.myFun = null;
t.myFun = TestFun1;
//事件不能在外部赋值
//t.myEvent = null;
//t.myEvent = TestFun1;
//但可以+= -=
t.myEvent+= TestFun1;
//委托可以在外部调用
t.myFun();
t.myFun.Invoke();
//事件不能在外部调用
//t.myEvent();
//t.myEvent.Invoke();
//只能在类的内部去封装调用
t.DoEvent();
Action a = TestFun1;
//事件 不能作为临时变量在函数中使用、它连基本的赋值都做不到
// event Aciton ae = TestFun1;
}
static void TestFun1()
{
}
}