前言:

之前小猪曾经分享过自己对C#委托的一点理解 其实在使用委托的过程中我们会大量的使用拉姆达(=>)表达式

介绍:

"Lambda表达式"是一个匿名函数,是一种高效的类似于函数式编程的表达式,Lambda简化了开发中需要编写的代码量。它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型,支持带有可绑定到委托或表达式树的输入参数的内联表达式。所有Lambda表达式都使用Lambda运算符=>,该运算符读作"goes to"。Lambda运算符的左边是输入参数(如果有),右边是表达式或语句块。Lambda表达式x => x * x读作"x goes to x times x"。

自C#3.0开始,就可以使用这种代码赋予委托。只要有委托参数类型的地方,就可以使用Lambda表达式。

ps:lambda表达式的语法比匿名方法简单。如果所调用的方法有参数,且不需要参数,匿名方法的语法就比较简单,因为这样不需要提供参数。

namespace TimeBookMVC4.TEST
{
class Program
{
static void Main(string[] args)
{
string mid = ", middle part,"; Func<string, string> lambda = param =>
{
param += mid;
param += " and this was added to thes string.";
return param;
};
Console.WriteLine(lambda("Start of string"));
}
}
}

lambda运算符"=>"的左边列出了需要的参数,右边定义了赋予lambda变量的方法的实现代码。

参数

Lambda表达式有集中定义参数的方式。如果只有一个参数,只写出参数名就足够了。下面的Lambda表达式使用了参数s。因为委托类型顶了一个string参数,所以s的类型就是string。实现代码调用Strign.Format()方法来返回一个字符串,在调用该委托时,就把字符串写到控制台上:

            Func<string, string> oneparam = s => String.Format(
"change uppercase {0}",s.ToUpper());
Console.WriteLine(oneparam("test"));

如果委托使用多个参数,就把参数名放在花括号中。这里参数x和y的类型是double,由Func<double,double,double>委托定义:

            Func<double, double, double> twoparam = (x, y) => x * y;
Console.WriteLine(twoparam(3,2));

为了方便,可以在花括号中给变量名添加参数类型:

            Func<double, double, double> twoparam = (double x,double y) => x * y;
Console.WriteLine(twoparam(3,2));

多行代码

如果Lambda表达式只有一条语句,在方法块内就不需要花括号和return语句,因为编译器会添加一条隐式的return语句。

            Func<double, double> square = x => x * x;

添加花括号、return语句和分号是完全合法的,通常这比不添加这些括号更容易阅读:

            Func<double, double> square = x => {
return x*x;
}

但是,如果在Lambda表达式的实现代码中需要多条语句,就必须添加花括号和return语句:

            Func<string, string> lambda = param =>
{
param += mid;
param += " and this was added to thes string.";
return param;
};

Lambda表达式外部的变量

通过Lambda表达式可以访问Lambda表达式块外部的变量。这是一个非常好的功能,但如果未正确使用,也会非常危险。

在下面的示例中,Fun<int,int>类型的Lambda表达式需要一个int参数,返回一个int。该Lambda表达式的参数用变量x定义。实现代码还访问了Lambda表达式外部的变量someVal。只要不认为在调用f时,Lambda表达式创建了一个以后使用的新方法,这似乎么有什么问题。看看这个代码块,调用f的返回值应是x加5的结果,但似乎不是这样:

            int someVal = 5;
Func<int, int> f = x => x + someVal;

假定以后要修改变量someVal,于是调用Lambda表达式时,会使用someVal的新值。调用f(3)的结果是10:

someVal =7;

Console.WriteLine(f(3));

特别是,通过另一个线程调用Lambda表达式时,我们可能不知道进行了这个调用,也不知道外部变量的当前值是什么。

现在我们也许会奇怪,如何在Lambda表达式的内部访问Lambda表达式外部的变量。为了理解这一点,看看编译器在定义Lambda表达式时做了什么。对于Lambda表达式x=>x+someVal,编译器会创建一个匿名类,他有一个构造函数来传递外部变量。该构造函数取决于从外部传递进来的变量个数。对于这个简单的例子,构造函数接收一个int。匿名类包涵一个匿名方法,其实现代码、参数和返回类型有Lambda变大事定义:

        public class AnonymousClass
{
private int someVal;
public AnonymousClass(int someVal)
{
this.someVal = someVal;
}
public int AnonymousMethod(int x)
{
return x + someVal;
}
}

使用Lambda表达式并调用该方法,会创建匿名类的一个实例,并传递调用该方法时变量的值。

参考:《C#高级编程(第七版)》

C#拉姆达(=>)表达式的更多相关文章

  1. 如何用拉姆达表达式(Lambda Expressions) 书写左链接查询

    在C#中,如果要实现两个列表的左链接查询,我们的一般用法就是用的linq表达式就是 List<Pet> pets = }, }, } }; List<Pet2> pets2 = ...

  2. SqlSugar常用查询实例-拉姆达表达式

    SqlSugar支持拉姆达表达式查询,匿名对象参数等,相对还是比较方便好用的. 一.查询列表: //查询列表 SqlSugarClient db = SugarContext.GetInstance( ...

  3. 拉姆达表达式(Lambda Expressions)

    上面两种写法是一样的 ,拉姆达表达式也是一种委托, 但引用的是匿名方法

  4. C# 匿名方法和拉姆达表达式

    有时候,我们需要封装一组数据,只有数据,没有方法,并且只用于当前程序,不需要在项目间重用,这时候,如果是传统的使用类来封装的话,大概会是下面这种样子: internal class SomeData ...

  5. .net 在同步方法中使用拉姆达表达式执行async/await异步操作

    代码如下: static void Main(string[] args) { ((Action)(async () =>{ var data = await HttpHelper.GetOnS ...

  6. (转)拉姆达表达式(Lambda Expressions) =>写法的涵义

      lambdaclass编译器 让我们先看一个简单的拉姆达表达式: x=>x/2 这个表达式的意思是:x为参数,对x进行相应的操作后的结果作为返回值. 通过这个拉姆达表达式,我们可以看到: 这 ...

  7. EasyUI 之 DataGrid利用用拉姆达表达式实现分页查询

      首先,我们在DataGrid的URL中加上我们要查询的条件:查询用户名不是“呵呵”的所有用户. <div> <table id="dg" class=&quo ...

  8. c# 拉姆达表达式实现List去重

    c# 拉姆达表达式实现List去重 var list = studentlist.OrderByDescending(a => a.CreateDate).ToList(); Console.W ...

  9. Lambda拉姆达表达式

    拉姆达表达式常用于委托,也就是说拉姆达表达式是匿名函数,简单点就是函数. a => a.Equals("string"); //原形为: (a) => { return ...

随机推荐

  1. 04 SQL是关于集合的

    面向集合去思考 要想成为写SQL语句的高级专家, 最困难的是一个转变就是从面相过程的思维方式转变到面相集合的思维方式. 首先要停止那些一次处理一行数据的过程化步骤思维, 试着把思路转移到使用类似于 “ ...

  2. asp.net实现大文件上传

    需要下载NeatUpload插件 上传页面: <%@ Page Language="C#" AutoEventWireup="true" CodeFile ...

  3. Java源码初学_HashMap

    一.概念 HashMap的实例有两个参数影响其性能:初始容量和加载因子.容量是哈希表中桶的数量,初始容量只是哈希表在创建时的容量.加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度.当哈希表 ...

  4. TortoiseSvn

    TortoiseSVN 是svn版本控制系统的一个免费开源客户端,它是svn版本控制的 Windows 扩展.可以使你避免使用枯燥而且不方便的命令行.它完全嵌入 Windows Explorer,使用 ...

  5. 在Android中查看和管理sqlite数据库

    在Android中可以使用Eclipse插件DDMS来查看,也可以使用Android工具包中的adb工具来查看.android项目中的sqlite数据库位于/data/data/项目包/databas ...

  6. Android控件之Button(按钮控件)和ImageButton(图片按钮控件)

    一.Button和ImageButton特证: 1.共同特证: 都可以作为一个按钮产生点击事件 2.不同特证: Button有text的属性,ImageButton没有 ImageButton有src ...

  7. JavaScript的事件对象_事件流

    事件流事件流是描述的从页面接受事件的顺序,当几个都具有事件的元素层叠在一起的时候,那么你点击其中一个元素,并不是只有当前被点击的元素会触发事件,而层叠在你点击范围的所有元素都会触发事件.事件流包括两种 ...

  8. SDL2.0的VS开发环境搭建

    SDL2.0的VS开发环境搭建 [前言] 我是用的是VS2012,VS的版本应该大致一样. [开发环境搭建] >>>SDL2.0开发环境配置:1.从www.libsdl.org 下载 ...

  9. MYSQL 编码方式 ------导入 .sql 文件 报编码错误

    在做计量泵上位机时,利用MYSQL存储数据,建表hisruninfo(计量泵历史运行数据表). 表格式为utf8,查过数据库 格式 同样为utf8 导入该hisruninfo.sql文件时,并没有报错 ...

  10. 开机使用root用户登录

    有的fedora版本默认不支持开机以root用户登录,这是出于安全机制的考虑,可以通过设置实现开机root用户登录 步骤: 1.修改.etc/pam.d/gdm文件,注释掉auth  pam_succ ...