目录
前期准备:在类的内部定义几个委托和方法
//先定义几个自定义委托
public delegate void NoReturnNoPara();
public delegate void NoReturnHasPara(int x, int y);
public delegate string HasReturnNoPara();
public delegate int HasReturnHasPara(int x, int y);
/// <summary>
/// 无参无返回值的函数
/// </summary>
private void NoReturnNoParaMethod()
{
Console.WriteLine("无参数无返回值的方法");
}
/// <summary>
/// 有参数无返回值的函数
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
private void NoReturnHasParaMethod(int x, int y)
{
Console.WriteLine($"{x}+{y}={x + y}");
}
一、lambda在framework 1.0版本中的形态
在1.0时代,如果要写一个lambda表达式,需要分三步:
- 需要定义一个委托和一个方法
- 实例化一个委托时将这个方法传递过去
- 最后执行这个委托
/// <summary>
/// 在framework 1.0版本中的形态
/// </summary>
public void FrameworkV1()
{
/*
* 在1.0时代:
* 1、需要定义一个委托和一个方法
* 2、实例化一个委托时将这个方法传递过去
* 3、最后执行这个委托
*/
Console.WriteLine("=====================framework 1.0版本中的形态======================");
//无参无返回值
NoReturnNoPara noReturnNoPara = new NoReturnNoPara(NoReturnNoParaMethod);
noReturnNoPara.Invoke();
//有参数无返回值
NoReturnHasPara noReturnHasPara = new NoReturnHasPara(NoReturnHasParaMethod);
noReturnHasPara.Invoke(1, 2);
//And so on....
}
二、lambda在framework 2.0版本中的形态
在2.0时代,如果要写一个lambda表达式,也需要分三步,但是在传递函数的时候有所区别,不需要单独定义方法:
- 定义一个委托
- 在实例化委托时,直接传递一个delegate关键字修饰的匿名方法
- 执行委托
这样也带来了一个优点:可以访问到除了参数以外的局部变量
/// <summary>
/// 在framework 2.0版本中的形态
/// </summary>
public void FrameworkV2()
{
/*
* 在2.0时代:
* 1、定义一个委托
* 2、在实例化委托时,直接传递一个delegate关键字修饰的匿名方法
* 3、执行委托
* 优点:可以访问到除了参数以外的局部变量
*/
Console.WriteLine("=====================framework 2.0版本中的形态======================");
string para = "我是局部变量";
//有参数无返回值
NoReturnHasPara noReturnHasPara = new NoReturnHasPara(delegate (int x, int y)
{
Console.WriteLine($"{x}+{y}={x + y}");
//可以访问到局部变量
Console.WriteLine(para);
});
noReturnHasPara.Invoke(1, 2);
//And so on....
}
三、lambda在framework 3.0版本中的形态
1、3.0初期版本中的形态
在3.0初期版本,对lambda表达式进一步简化
- 定义一个委托
- 在实例化委托时,去掉了delegate关键字,在参数和方法体之间使用"=>"连接(读作goes to)
- 执行委托
/// <summary>
/// 在framework 3.0版本中的形态
/// </summary>
public void FrameworkV3()
{
/*
* 在3.0时代:
* 1、定义一个委托
* 2、在实例化委托时,去掉了delegate关键字,在参数和方法体之间使用"=>"(goes to)连接
* 3、执行委托
*/
Console.WriteLine("=====================framework 3.0版本中的形态======================");
//有参数无返回值
NoReturnHasPara noReturnHasPara = new NoReturnHasPara((int x, int y) =>
{
Console.WriteLine($"{x}+{y}={x + y}");
});
noReturnHasPara.Invoke(1, 2);
//And so on....
}
2、3.0后期版本中的形态发展
再到后来,进一步进行简化,逐渐接近现在我们所熟知的写法:
- 去掉参数类型,由编译器自动判断参数类型
- 如果lambda表达式只有一行,则可以省略大括号
- 实例化委托时,等号右边可以直接是lambda表达式,省略了new 委托
- lambda表达式只有一个参数的时候,可以直接省略掉参数的括号
- 如果lambda表达式中只有一行代码,而且有返回值,可以直接省略 return 关键字
/// <summary>
/// 在framework 3.0后期版本中的形态
/// </summary>
public void FrameworkV3x()
{
{
/*
* 在3.0后期版本:
* 1、定义一个委托
* 2、在实例化委托时,去掉了匿名方法的参数类型,由编译器自动推断参数类型(因为传递的函数的参数返回值必须与委托定义的参数返回值类型相同,所以编译器可以直接推断出匿名方法中的参数类型,这是编译器提供给开发者的便捷功能,也叫做语法糖)
* 3、执行委托
*/
Console.WriteLine("=====================framework 3.0后期版本中的形态======================");
//有参数无返回值
NoReturnHasPara noReturnHasPara = new NoReturnHasPara((x, y) =>
{
Console.WriteLine($"{x}+{y}={x + y}");
});
noReturnHasPara.Invoke(1, 2);
//And so on....
}
{
/*
* 在3.0后期版本继续发展:
* 1、定义一个委托
* 2、在实例化委托时,如果匿名方法的方法体中只有一行,直接可以去掉大括号
* 3、执行委托
*/
Console.WriteLine("=====================framework 3.0后期版本中的形态继续演变======================");
//有参数无返回值
NoReturnHasPara noReturnHasPara = new NoReturnHasPara((x, y) => Console.WriteLine($"{x}+{y}={x + y}"));
noReturnHasPara.Invoke(1, 2);
//And so on....
}
{
/*
* 在3.0后期版本继续发展:
* 1、定义一个委托
* 2、在实例化委托时,等号右边可以直接为匿名方法,省略 new 委托
* 3、执行委托
*/
Console.WriteLine("=====================framework 3.0后期版本中的形态继续演变======================");
//有参数无返回值
NoReturnHasPara noReturnHasPara = (x, y) => Console.WriteLine($"{x}+{y}={x + y}");
noReturnHasPara.Invoke(1, 2);
//And so on....
}
{
/*
* 在3.0后期版本继续发展:
* 1、定义一个委托
* 2、在实例化委托时,只有一个参数的时候,可以直接省略掉参数的括号
* 3、执行委托
*/
Console.WriteLine("=====================framework 3.0后期版本中的形态继续演变======================");
Action<string> action = s => Console.WriteLine(s);
action.Invoke("lambda发展史...");
//And so on....
}
{
/*
* 在3.0后期版本继续发展:
* 1、定义一个委托
* 2、在实例化委托时,如果lambda表达式中只有一行代码,而且有返回值,可以直接省略 return 关键字
* 3、执行委托
*/
Console.WriteLine("=====================framework 3.0后期版本中的形态继续演变======================");
//无参数,返回值为string类型
Func<string> func = () => "省略return 关键字";
func.Invoke();
//参数为int型,返回值为string型
Func<int, string> func1 = i => i.ToString();
func1.Invoke(1);
//And so on....
HasReturnNoPara hasReturnNoPara = () => "自定义委托返回值";
hasReturnNoPara.Invoke();
//两个参数
HasReturnHasPara hasReturnHasPara = (x, y) => x + y;
hasReturnHasPara.Invoke(1, 2);
}
}
四、lambda表达式的本质
从lambda表达式的发展可以看出:
- 1.0版本,实例化委托传递的是一个普通方法
- 2.0版本,实例化委托传递的是一个delegate关键字修饰的匿名方法
- 3.0及以后版本,实例化委托直接传递的是一个匿名方法
因此不难得到结论:lambda表达式其本质就是一个方法(函数),或者狭义的说是一个匿名方法