C# lambda表达式
学了N多久的委托,终于告一段落,现在可以开始lambda的学习之旅了,但是在说lambda之前必须先说下C#中的匿名方法.
1、匿名方法
下面是一个字符串拼接的程序,用到了委托,代码如下:
class Program
{
static void Main(string[] args)
{
string mid = ",middle part,";
var d1 = new GetString(Test);
string aa=d1("Start of string") + mid + "this is the End";
Console.WriteLine(aa);
Console.ReadLine();
}
static string Test(string add)
{
return add;
}
}
很简单的代码,下面把它用匿名方法来改写,代码如下:
class Program
{
static void Main(string[] args)
{
string mid = ",middle part,";
Func<string, string> func = delegate(string param)
{
param += mid;
param += "The end of string";
return param;
};
Console.WriteLine(func("The Start of String"));
Console.ReadLine();
}
}
匿名方法的优点:
a、减少了要编写的代码,不必定义由委托使用的方法
b、降低了代码的复杂度,尤其是定义了好几个事件时
但是,匿名方法的代码执行速度并没有加快,应为编译器还是会生成一个方法,所以使用匿名方法,还是会有以下限制:
a、在匿名方法中不能使用跳转语句(break、goto、continue)跳转到该匿名方法的外部,反之依然,外部跳转到里面也不能
b、在匿名方法中不能访问不安全的代码,另外也不能在匿名方法外部使用的ref或者out参数,但是可以使用在匿名方法外部定义的其他参数
2、Lamdba表达式
匿名方法虽然好,但是从C#3.0之后,推出了更好的Lamdba表达式,只要有委托参数的地方,就可以使用Lamdba表达式,现在改编上面的匿名方法用Lamdba表达式:
class Program
{
static void Main(string[] args)
{
string mid = ",middle part,";
Func<string, string> func = param =>
{
param += mid;
param += "The end of string";
return param;
};
Console.WriteLine(func("The Start of String"));
Console.ReadLine();
}
}
lamdba运算符"=>"的左边列出了需要的参数,右边定义了关于参数的实现方法体
如果委托有多个参数,就把参数名放到花括号中,代码如下:
class Program
{
static void Main(string[] args)
{
Func<double, double, double> func = (x, y) =>
{
return x * y;
};
Console.WriteLine(func(2, 3));
Console.ReadLine();
}
}
上面的代码可能会存在问题,当编译器不能匹配重载后的版本,那么这个时候,就需要给参数加上类型,代码如下:
class Program
{
static void Main(string[] args)
{
Func<double, double, double> func = (double x, double y) =>
{
return x * y;
};
Console.WriteLine(func(2, 3));
Console.ReadLine();
}
}
当Lamdba表达式方法体只有一行代码时,就不需要中括号,和return关键字,代码如下:
class Program
{
static void Main(string[] args)
{
Func<double, double, double> func = (double x, double y) => x * y;
Console.WriteLine(func(2, 3));
Console.ReadLine();
}
}
但是如果有多行代码就必须加中括号和return关键字了,有点类似与if else语句
2、Lamdba表达式闭包
闭包这个很多编程语言中都有,Lamdba表达式能访问表达式外部的变量就是通过闭包来实现的。闭包是一个非常好用的功能,但是使用不当,也会出现问题。代码如下:
class Program
{
static void Main(string[] args)
{
double value1 = 6;
Func<double, double> func = x => x + value1;
value1 = 7;
Console.WriteLine(func(1) + "...." + func(2));
Console.ReadLine();
}
}
输出:8和9并不是我们想的7和8,
原因在编译器处理外部变量的方式:对于lamdba表达式x=>x+value1,编译器会创建一个类,它有一个构造函数来初始化外部参数,
该构造函数的参数个数值取决于外部传递进来的参数个数,代码如下:
public class AnonymousClass
{
private int value1;
public AnonymousClass(int value1)
{
this.value1 = value1;
}
public int AnonymousMethod(int x)
{
return x + value1;
}
}
使用Lamdba表达式并调用该方法时,会创建匿名类的一个实例,并传递调用该方法时变量的值。
- 【选择题】Java基础测试四(15道)
- GO语言并发编程之互斥锁、读写锁详解
- GO语言标准错误处理机制error用法实例
- spring框架复习大纲【面试+提高】
- Go语言中的Array、Slice、Map和Set使用详解
- go的websocket实现原理与用法详解
- go语言base64加密解密的方法
- Go语言轻量级线程Goroutine用法实例
- Go语言的队列和堆栈实现方法
- Go语言使用sort包对任意类型元素的集合进行排序的方法
- TiDB 源码阅读系列文章(五)TiDB SQL Parser 的实现
- [go语言]吐槽:怎么样实现支持并发访问的数据集合更好?
- 利用缓冲信道来实现网游帐号验证消息的分发和等待
- Buffered channel、slice和mutex的简单性能测试
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 如何将CentOS7升级至CentOS8(详细步骤)
- leetcode树之二叉树的所有路径
- 如何利用Bash脚本监控Linux的内存使用情况
- Ubuntu18 给terminal改个漂亮的命令行提示符的方法
- leetcode树之将有序数组转换为二叉搜索树
- 在 Ubuntu 上安装 Protobuf 3 的教程详解
- protobuf简单介绍和ubuntu 16.04环境下安装教程
- Ubuntu解决火狐浏览器无法同步书签的问题【推荐】
- Ubuntu添加swap分区的方法
- linux文件目录管理命令整理总结
- C++核心准则SF.8:为所有的.h文件使用包含监护
- 利用logsave如何将命令输出保存起来
- CentOs下安装gcc/g++/gdb的方法
- 详解firewall的规则设置与命令(白名单设置)
- 二叉树:构造一棵最大的二叉树