C#自学笔记:匿名函数与Lambda表达式
匿名函数
没有名字的函数匿名函数的使用主要是配合委托和事件进行使用
脱离委托和事件,是不会使用匿名函数的
基本语法
delegate (参数列表)
{
//函数逻辑
};
何时使用?
- 函数中传递委托参数时
- 委托或事件赋值时
使用
相当于直接声明了一个没有名字的函数,然后直接放进委托的容器中存起来//1. 无参无返回值
Action a = delegate()
{
Console.WriteLine("匿名函数逻辑");
};
a();
//2. 有参
Action<int, string> b = delegate (int a, string b)
{
Console.WriteLine(a);
Console.WriteLine(b);
};
b(100, "123");
//3. 有返回值
Func<string> c = delegate()
{
return "123123";
};
Console.WriteLine(c());
//4. 一般情况下会作为函数参数传递或者作为函数返回值
Test t = new Test();
//参数传递
t.Dosomthing(100, delegate()
{
Console.WriteLine("匿名函数逻辑");
});
//返回值
Action ac = t.GetFun();
ac();
//一步到位,直接调用返回的委托函数
t.GetFun()();
class Test
{
public void Dosomthing(int a, Action fun)
{
Console.WriteLine(a);
fun();
}
//作为返回值
public Action GetFun()
{
return delegate()
{
};
}
}
缺点
添加到委托或事件容器中后不记录,无法单独移除- 因为匿名函数没有名字,所以没有办法指定移除某一个匿名函数
- 就算写的逻辑一模一样也是没有用的,相当于两个函数了
要移除只能通过把整个委托或事件容器清空
ac = null;
lambad表达式
可以理解为匿名函数的简写除了写法不一样,使用上一模一样
都是和委托或者事件配合使用的
语法
//匿名函数
delegate (参数列表)
{
};
//lambad表达式
(参数列表) =>
{
};
使用
//1. 无参无返回值
Action a = () =>
{
//逻辑
};
//2. 有参无返回值
Action<int> a2 = (int value) =>
{
Console.WriteLine(value);
};
//3. 甚至参数类型都可以省略
Action<int> a3 = (value) =>
{
Console.WriteLine(value);
};
//4. 有参有返回值
Func<string, int> a4 = (value) =>
{
Console.WriteLine(value);
return 1;
};
Console.WriteLine(a4("123123"));
缺点也和匿名函数一样
闭包
内层的函数可以引用包含在它外层的函数的变量即使外层函数的执行已经终止
注意:该变量提供的值并非变量创建时的值,而是在父函数范围内的最终值。
class Test
{
public event Action action;
public Test()
{
int value = 10;
//这里就形成了闭包
action = () =>
{
Console.WriteLine(value);
};
//注意
for (int i = 0; i < 10; i++)
{
action += () =>
{
Console.WriteLine(i);//调用action时打印出来的全是10
};
int index = i;
action += () =>
{
Console.WriteLine(index);//这里打印出来就是0-9
};
}
}
}
理应上 Test 函数运行完 value 要被回收,由于在 action 中存进了一个匿名函数,value 就不会被回收,只有在 action 置空才会被回收
存进去的是变量的地址而不是值,所以在调用时会找到该地址,获取变量的最终值。
List排序
List自带排序方法
List<int> list = new List<int>();
list.Add(2);
list.Add(5);
//默认是升序排序
list.Sort();
int泛型可以自动排序是因为系统帮我们写好了排序的方法
自定义类的排序
如果是自定义类想要使用list自带的排序方法时,需要继承一个排序接口,实现一个排序的规则class Item : IComparable<Item>
{
public int money;
public Item(int money)
{
this.money = money;
}
public int CompareTo(Item other)
{
//返回值的含义
//小于0:当前对象放在传入对象的前面
//等于0:保持当前的位置不变
//大于0:当前对象放在传入对象的后面
//可以简单理解为传入对象的位置就是0
//如果返回值为负数,我就放在它的左边
//如果返回值为正数,我就放在它的右边
if (this.money > other.money)
{
return 1;
}
else
{
return -1;
}
}
}
List<Item> items = new List<Item>();
items.Sort();
通过委托函数进行排序
List.Sort()底层public void Sort();
public void Sort(Comparison<T> comparison);
public delegate int Comparison<in T>(T x, T y);
Comparison是个委托,可以传入函数进行排序
使用
List<ShopItem> shopItems = new List<ShopItem>();
shopItems.Add(new ShopItem(2));
shopItems.Add(new ShopItem(1));
shopItems.Sort(SortShopItem);
static int SortShopItem(ShopItem a, ShopItem b)
{
if (a.id > b.id)
{
return 1;
}
else
{
return -1;
}
}
//简化:用匿名函数 -> 省去delegate声明和参数类型 -> lambad表达式 -> 三目运算符
shopItems.Sort((a, b) =>
{
return a.id > b.id ? 1 : -1;
};
个人用的最多的是第三种方式

浙公网安备 33010602011771号