闭包
/// <summary>
/// 闭包
/// 1、函数嵌套,一个函数内部有另一个函数,并且内部函数有外部函数的局部变量
/// 2、闭包会捕获周围环境的自由变量(局部变量)
/// 3、闭包会将内部函数作为返回值返回,供外部函数调用
/// </summary>
public class Demo3
{
/// <summary>
/// 在这个方法中lambda表达式有延迟
/// 它捕获的是变量的引用,而不是创建时候的变量
/// 结束后的2
/// </summary>
/// <param name="count"></param>
/// <returns></returns>
public Action<int>[] CreateAction(int count=3)
{
var action = new Action<int>[count];
for (int i = 0; i < count; i++)
{
Console.WriteLine("-------开始------");
action[i] = x => Console.WriteLine(x * i);
Console.WriteLine("--------结束------");
/* Console.WriteLine("-------开始------");
int j = i;
action[i] = x => Console.WriteLine(x * j);
Console.WriteLine("--------结束------");*/
}
return action;
}
public void GetAction()
{
var action = CreateAction();
action[0].Invoke(10);
action[1].Invoke(10);
action[2].Invoke(10);
}
/// <summary>
/// 使用string能更好的看出来,lambda是调的引用
/// 垃圾回收是追踪和释放不被程序使用的内存对象
/// 而闭包没有被程序调用的时候,也是垃圾,是会被回收的。
/// 但是有一点,闭包引用的自由变量也就是局部变量,是其他代码的引用
/// 所以只要有一个活跃的引用,闭包不会被回收,而导致内存泄漏
/// 为了避免这种情况,应该在合理的时候,手动订阅事件,取消闭包,回收垃圾
/// </summary>
/// <param name="count"></param>
/// <returns></returns>
public Action<string>[] CreateActionString(int count = 3)
{
var action = new Action<string>[count];
for (int i = 0; i < count; i++)
{
action[i] = x => Console.WriteLine(x+"开始");
}
return action;
}
public void GetActionString()
{
var action = CreateActionString();
action[0].Invoke("10");
action[1].Invoke("10");
action[2]("10");
Console.ReadLine();
}
}
使用引用类型,故意报错,可查看闭包的调用情况
public class Demo5
{
/* public static Action<int>[] CreateAction(int count = 3)
{
var action = new Action<int>[count];
var multipliers = new int[count]; // 创建一个数组来存储乘数
// 初始化 multipliers 数组的值
for (int i = 0; i < count; i++)
{
multipliers[i] = i;
}
// 为每个行动创建一个委托
for (int i = 0; i < count; i++)
{
// 闭包捕获 multipliers 数组中的特定元素
action[i] = x => Console.WriteLine(x * multipliers[i]);
}
return action;
}*/
/// <summary>
/// 这两种方法都会报错,循环结束后的值是3
/// </summary>
/// <param name="count"></param>
/// <returns></returns>
public static Action<int>[] CreateAction(int count = 3)
{
var action = new Action<int>[count];
var multipliers = new Dictionary<int, int>(); // 创建一个字典来存储乘数
// 填充字典与乘数
for (int i = 0; i < count; i++)
{
multipliers[i] = i;
}
var str1=multipliers.Keys.ToArray();
var str2=multipliers.Values.ToArray();
// 为每个行动创建一个委托
for (int i = 0; i < count; i++)
{
// 闭包捕获字典中的特定键
action[i] = x => Console.WriteLine(x * multipliers[i]);
}
return action;
}
public static void GetAction()
{
var action = CreateAction();
action[0].Invoke(10);
action[1].Invoke(10);
action[2].Invoke(10);
}
}
本文作者:孤沉
本文链接:https://www.cnblogs.com/guchen33/p/18084187
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步