字数
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 委托类型 事件名;
事件的使用:
- 事件是作为成员变量存在于类中
- 事件和委托的使用基本一模一样 事件相对于委托的区别:
- 不能在==类外部==赋值,但是可以
加减
去添加移除记录的函数 - 不能再==类外部==调用 注意:它只能作为成员存在于类和接口以及结构体中
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();
}
}
贡献者
worldddddd