在写代码的过程中,并不是任何时候都会把一个代码块放在一个命名函数中,而且有可能的情况是:函数太多或者已有相似名称的函数,已经不知道要怎么去命名为好;又或者给中间函数命名后意义不大,基本不会复用......所以匿名函数不失为一种合适的选择。
匿名函数的实现有多种方式(委托、匿名方法),另外需要注意的是尽管使用匿名函数尽管可以让代码变得简洁,但是要对匿名函数的正确使用引起充分的重视。如下代码:
using System;
delegate void D();
class Test
{
static D[] F1()
{
D[] result = new D[3];
int x;//注意区别
for (int i = 0; i < 3; i++)
{
x = i * 2 + 1;
result[i] = () => { Console.WriteLine("F1 result="+x.ToString()); };
}
return result;
}
static D[] F2()
{
D[] result = new D[3];
for (int i = 0; i < 3; i++)
{
int x = i * 2 + 1;//注意区别
result[i] = () => { Console.WriteLine("F2 result=" + x.ToString()); };
}
return result;
}
static D[] F3()
{
D[] result = new D[3];
for (int i = 0; i < 3; i++)
{
//注意区别
result[i] = () => { Console.WriteLine("F3 result=" + i.ToString()); };
}
return result;
}
static void Main() {
foreach (D d in F1()) d();//5 5 5
foreach (D d in F2()) d();//1 3 5 ,这个才是想要的输出
foreach (D d in F3()) d();//3 3 3
}
}
输出结果如下:
为何F1、F3没有按意料中类似F2地输出?原因参见微软文档中在“表达式”一节对匿名函数的描述:表达式
个人关于C#的一些语法及基础演练源码,Git地址为:CSharpBasicCodePractice,如果对您有一定帮助,还望不吝点个Star,谢谢!
是一种引用类型,本质是方法指针。介绍:委托
个人较常用的场景,在创建线程时:
Thread t0 = new Thread(new ThreadStart(delegate { Console.WriteLine("delegate"); }));
t0.Name = "t0";
t0.Start();
都是委托的一种表示方式(即.Net的内设委托),本质上都是委托。
Func有可选参数,有返回类型;
Action有可选参数,无返回;
Predicate有参数(默认一个,多个参数需要较复杂的实现),固定返回bool类型;(多用于对数组和集合的查询操作中作为参数,如数组的Find函数)
这三个函数中Action会使用的较多,比在WPF的线程调度器中对UI进行修改:
this.Dispatcher.BeginInvoke((Action)(() =>
{
Console.WriteLine("this is lambda");
}));
Predicate的用法,简单举例如下:
List lists = new List() { "T0", "T1" };
Predicate isT0 = new Predicate(IsT0);//true如果obj满足此委托; 所表示的方法中定义的条件否则为false。
List T0 = lists.FindAll(isT0);
List T0_lambda = lists.FindAll(ss =>ss == "T0";);//lambda表达式写法
private static bool IsT0(string ss)
{
return ss == "T0";
}
可以查看本人的git库中的“MultiThreadDemo”块,地址:C#基础及语法演练
它并非C#语言独有的特性,它是委托的一种形式,内部原理与匿名委托类似,参考:委托和 lambda
其中一个例子认为很有用,将lambda表达式作为事件处理程序,如下:
public MainWindow()
{
InitializeComponent();
Loaded += (o, e) =>
{
this.Title = "Loaded";
};
}
委托定义指定特定方法签名的类型。 可将满足此签名的方法(静态或实例)分配给该类型的变量,然后(使用适当参数)直接调用该方法,或将其作为参数本身传递给另一方法再进行调用。
为简化开发过程,.NET 包含一组委托类型,程序员可重用这些类型而无需创建新类型。 这些类型是 Func<>
、Action<>
和 Predicate<>
,可以使用它们而无需定义新的委托类型。
lambda 表达式(或简称“lambda”)在 C# 3.0 中作为语言集成查询 (LINQ) 的核心构建基块被引入。 这种表达式只是使用委托的更方便的语法。 它们将声明签名和方法正文,但在分配到委托之前没有自己的正式标识。 与委托不同,可将其作为事件注册的右侧内容或在各种 LINQ 子句和方法中直接分配。