本笔记摘抄自:https://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html,记录一下学习过程以备后续查用。

    一、Lambda 的意义

在Framework 2.0 以前,声明委托的唯一方法是通过方法命名,从Framework 2.0 起,系统开始支持匿名方法。通过匿名方法,可以直接把一段代码绑定

给事件,因此减少了实例化委托所需的编码系统开销。而在 Framework 3.0 开始,Lambda表达式开始逐渐取代了匿名方法,作为编写内联代码的首选方式。

总体来说,Lambda 表达式的作用是为了使用更简单的方式来编写匿名方法,彻底简化委托的使用方式。

二、回顾匿名方法的使用

匿名方法的使用在C#委托与事件学习笔记中有简单介绍过,在此回顾一下:

        static void Main(string[] args)
{
#region 事件的使用及方法绑定
PersonManager personManager = new PersonManager();
//绑定事件处理方法方式一
personManager.MyEvent += new MyDelegate(GetName);
//绑定事件处理方法方式二
personManager.MyEvent += GetName;
//绑定事件处理方法方式三(匿名方法)
personManager.MyEvent += delegate (string name) { Console.WriteLine("My name is " + name); };
personManager.Execute("Atomy");
Console.Read();
#endregion
}

总是使用 delegate(){......} 的方式建立匿名方法,令人不禁感觉郁闷。于是从Framework 3.0起,Lambda表达式开始出现。

    三、简单介绍泛型委托

在介绍Lambda表达式前,先介绍一下常用的几个泛型委托。

    3.1 泛型委托 Predicate<T>

早在Framework 2.0的时候,微软就为List<T>类添加了Find、FindAll、ForEach等方法用作数据的查找。

public T Find ( Predicate<T> match)

public List<T> FindAll(Predicate<T>  match)

在这些方法中存在一个Predicate <T> 表达式,它是一个返回bool的泛型委托,能接受一个任意类型的对象作为参数。

public delegate bool Predicate<T>(T obj)

在下面例子中,Predicate委托绑定了参数为Person类的方法Match作为查询条件,然后使用FindAll方法查找到合适条件的List<Person>集合。

    class Program
{
#region 泛型委托 Predicate<T>
/// <summary>
/// Person类
/// </summary>
class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; } public Person(int id, string name, int age)
{
Id = id;
Name = name;
Age = age;
}
} /// <summary>
/// 数据源
/// </summary>
/// <returns></returns>
static List<Person> GetList()
{
var personList = new List<Person>();
var person = new Person(, "Hello", );
personList.Add(person);
person = new Person(, "World", );
personList.Add(person);
return personList;
} /// <summary>
/// 查询条件
/// </summary>
/// <param name="person"></param>
/// <returns></returns>
static bool Match(Person person)
{
return person.Age <= ;
}
#endregion static void Main(string[] args)
{
#region 泛型委托 Predicate<T>
List<Person> list = GetList();
//绑定查询条件
Predicate<Person> predicate = new Predicate<Person>(Match);
List<Person> result = list.FindAll(predicate);
Console.WriteLine($"Person count is : {result.Count}");
Console.Read();
#endregion
}
}

运行结果如下:

    3.2 泛型委托 Action

Action<T> 的使用方式与 Predicate<T> 相似,不同之处在于 Predicate<T> 返回值为 bool ,  Action<T> 的返回值为 void。

Action 支持0~16个参数,可以按需求任意使用。

public delegate void Action()

public delegate void Action<T1> (T1 obj1)

public delegate void Action<T1,T2> (T1 obj1, T2 obj2)

public delegate void Action<T1,T2,T3> (T1 obj1, T2 obj2,T3 obj3)

............

public delegate void Action<T1,T2,T3,......,T16> (T1 obj1, T2 obj2,T3 obj3,......,T16 obj16)

下面代码演示泛型委托Action:

    class Program
{
#region 泛型委托 Action
static void ShowMessage(string message)
{
Console.WriteLine(message);
}
#endregion static void Main(string[] args)
{
#region 泛型委托 Action
Action<string> action = ShowMessage;
action("Hello World");
Console.ReadKey();
#endregion
}
}

运行结果如下:

    3.3 泛型委托 Func

委托Func与Action相似,同样支持0~16个参数,不同之处在于Func必须具有返回值。

public delegate TResult Func<TResult>()

public delegate TResult Func<T1,TResult>(T1 obj1)

public delegate TResult Func<T1,T2,TResult>(T1 obj1,T2 obj2)

public delegate TResult Func<T1,T2,T3,TResult>(T1 obj1,T2 obj2,T3 obj3)

............

public delegate TResult Func<T1,T2,T3,......,T16,TResult>(T1 obj1,T2 obj2,T3 obj3,......,T16 obj16)

下面代码演示泛型委托Func:

    class Program
{
#region 泛型委托 Func
static double Account(double a, bool condition)
{
if (condition)
return a * 1.5;
else
return a * ;
}
#endregion static void Main(string[] args)
{
#region 泛型委托 Func
Func<double, bool, double> func = Account;
double result = func(, true);
Console.WriteLine($"Result is : {result}");
Console.Read();
#endregion
}
}

运行结果如下:

四、揭开 Lambda 神秘的面纱

Lambda的表达式的编写格式如下:x=> x * 1.5

当中 “ => ”是Lambda表达式的操作符,在左边用作定义一个参数列表,右边可以操作这些参数。

例子一:先把int x设置1000,通过Action把表达式定义为x=x+500,最后通过Invoke激发委托。

    class Program
{
static void Main(string[] args)
{
#region Lambda例子一
int x = ;
Action action = () => x = x + ;
action.Invoke(); Console.WriteLine($"Result is : {x}");
Console.Read();
#endregion
}
}

运行结果如下:

例子二:通过Action<int>把表达式定义x=x+500,到最后输入参数1000,得到的结果与例子一相同。

注意,此处Lambda表达式定义的操作使用{ }括弧包括在一起,里面可以包含一系列的操作。

    class Program
{
static void Main(string[] args)
{
#region Lambda例子二
Action<int> action = (x) =>
{
x = x + ;
Console.WriteLine($"Result is : {x}");
};
action.Invoke();
Console.Read();
#endregion
}
}

运行结果如下:

例子三:定义一个Predicate<int>,当输入值大约等于1000则返回true,否则返回false。与3.1的例子相比,Predicate<T>的绑定不需要显式建立一个方法,

而是直接在Lambda表达式里完成,简洁方便了不少。

    class Program
{
static void Main(string[] args)
{
#region Lambda例子三
Predicate<int> predicate = (x) =>
{
if (x >= )
return true;
else
return false;
};
bool result = predicate.Invoke();
Console.WriteLine($"Result={result}");
Console.Read();
#endregion
}
}

运行结果如下:

例子四:在计算商品的价格时,当商品重量超过30kg则打9折,其他按原价处理。此时可以使用Func<double,int,double>,参数1为商品原价,参数2为商品

重量,最后返回值为 double 类型。

    class Program
{
static void Main(string[] args)
{
#region Lambda例子四
Func<double, int, double> func = (price, weight) =>
{
if (weight >= )
return price * 0.9;
else
return price;
};
double totalPrice = func(200.0, );
Console.WriteLine($"TotalPrice={totalPrice}");
Console.Read();
#endregion
}
}

运行结果如下:

例子五:使用Lambda为Button定义Click事件的处理方法,使用Lambda比使用匿名方法更加简单。

    public partial class Main : Form
{
public Main()
{
InitializeComponent();
} private void Main_Load(object sender, EventArgs e)
{
#region Lambda例子五
btnEvent.Click += (obj,arg)=>
{
MessageBox.Show("Hello World");
};
#endregion
}
}

运行结果如下:

例子六:此处使用3.1的例子,在List<Person>的FindAll方法中直接使用Lambda表达式。相比之下,使用Lambda表达式,不需要定义Predicate<T>对象,也

不需要显式设定绑定方法,简化了不工序。

    class Program
{
#region 泛型委托 Predicate<T>
/// <summary>
/// Person类
/// </summary>
class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; } public Person(int id, string name, int age)
{
Id = id;
Name = name;
Age = age;
}
} /// <summary>
/// 数据源
/// </summary>
/// <returns></returns>
static List<Person> GetList()
{
var personList = new List<Person>();
var person = new Person(, "Hello", );
personList.Add(person);
person = new Person(, "World", );
personList.Add(person);
return personList;
} /// <summary>
/// 查询条件
/// </summary>
/// <param name="person"></param>
/// <returns></returns>
static bool Match(Person person)
{
return person.Age <= ;
}
#endregion static void Main(string[] args)
{
#region Lambda例子六
List<Person> personList = GetList();
//查找年龄少于30年的人
List<Person> result = personList.FindAll((person) => person.Age <= );
Console.WriteLine("Person count is : " + result.Count);
Console.Read();
#endregion
}
}

运行结果如下:

当在使用LINQ技术的时候,到处都会弥漫着Lambda的身影,此时更能体现Lambda的长处。但LINQ涉及到分部类、分部方法、IEnumerable<T>、迭代器等

多方面的知识,这些已经超出本章的介绍范围。通过这一节的介绍,希望能够帮助大家更深入地了解Lambda的使用。

C# Lambda表达式学习笔记的更多相关文章

  1. java lambda表达式学习笔记

    lambda是函数式编程(FP,functional program),在java8中引入,而C#很早之前就有了.在java中lambda表达式是'->',在C#中是‘=>’. 杜甫说:射 ...

  2. lambda 表达式学习笔记

    在Java中传递一个代码段并不容易,不能直接传递代码段.Java是一个面向对象语言,所以必须构造一个对象,这个对象的类需要一个方法能包含所需的代码.lambda的出现有效的解决这个问题,让代码变得更加 ...

  3. python函数和lambda表达式学习笔记

    1. python函数 不同于其他语言,python支持函数返回多个值 为函数提供说明文档:help(函数名)或者函数名.__doc__ def str_max(str1, str2): ''' 比较 ...

  4. Lambda表达式学习笔记

    Lambda基础语法 Java8中引入了一个新的操作符" -> ",该操作符被称为箭头操作符或Lambda操作符,箭头操作符将Lambda表达式拆分成两部分: 左侧:Lamb ...

  5. C# Lambda 表达式学习之(三):动态构建类似于 c => c.Age == null || c.Age > 18 的表达式

    可能你还感兴趣: 1. C# Lambda 表达式学习之(一):得到一个类的字段(Field)或属性(Property)名,强类型得到 2. C# Lambda 表达式学习之(二):LambdaExp ...

  6. C# Lambda 表达式学习之(四):动态构建类似于 c => c.Age == 2 || c.Age == 5 || c => c.Age == 17 等等一个或多个 OrElse 的表达式

    可能你还感兴趣: 1. C# Lambda 表达式学习之(一):得到一个类的字段(Field)或属性(Property)名,强类型得到 2. C# Lambda 表达式学习之(二):LambdaExp ...

  7. Lamda表达式学习笔记二

    Lamda表达式学习笔记二 lamda表达式----方法引用 上一篇讲到Lamda体就是对函数式接口方法的实现 ,在方法体中我们可能会引用其他方法实现逻辑,所以在lamda体中我们可以直接引用器方法 ...

  8. Lamda表达式学习笔记一

    Lamda表达式学习笔记一 一.Lamda语法诠释 三傻大闹宝莱坞的主人公兰彻说的一句话让我映像深刻:用简单的语言来表达同样的意 我并不是说书上的定义怎么怎么不对,而是应该理解书本上的定义,并用简单的 ...

  9. java 8 中lambda表达式学习

    转自 http://blog.csdn.net/renfufei/article/details/24600507 http://www.jdon.com/idea/java/10-example-o ...

随机推荐

  1. T100——动态更改Label的说明

    例子: #設定科目名稱    IF g_prog = 'aapt300' THEN       CALL cl_set_comp_att_text("lbl_apca036",cl ...

  2. Java进阶开发-基于Base64的加密与解密操作

    基于Base64的加密与解密操作 正常来讲加密基本上永远伴随着解密,所谓的加密或者解密往往都是需要有一些所谓的规则.在JDK1.8开始提供有一组新的加密处理操作,Base64处理.在这个类里面有两个内 ...

  3. JDBC24homework

    编写程序: 创建一个类DBTools,在DBTools中创建一个方法find,find方法用于对数据库进行查询操作,现在要求将结果集封装成数组线性表嵌套数组的形式: ArrayList<Stri ...

  4. LinqToSQL3

    Lambda Lambda表达式和匿名方法很相似,但Lambda表达式比匿名方法更灵活,并且语法比匿名方法更简洁. 在LINQ中可以使用Lambda表达式创建委托,这些委托将稍后执行查询时被调用. L ...

  5. python 的面试题总汇

    函数作用域; LEGB : L>E>G>B L : local函数内部作用域 E : enclosing函数内部与内嵌函数之间 G : global全局作用域 B : build-i ...

  6. 深入探讨java的类加载器

    类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK 1.0 就出现了,最初是为了满足 Ja ...

  7. day09 并发编程

    一. 目录 1.进程的概念和两种创建方式 2.多进程爬虫 3.守护进程 4.进程队列 5.进程队列简单应用(实现数据共享) 6.线程的两种创建方式 7.线程和进程的效率对比 8.线程共享统一进程的数据 ...

  8. vue 日常开发小细节

    1. element-ui 日期选区禁用,设置属性 disabledDate: (time) => { const curDate = (new Date()).getTime() const ...

  9. vue项目默认IE以最高级别打开

    只需要在index.html加入 <meta http-equiv="X-UA-Compatible" content="IE=Edge">

  10. MacBook Pro实现共享屏幕(多台mac之间)

    1 开启允许所有用户控制屏幕     设置— 共享           2 在另一台MacBook Pro里打开finder窗口,并设置好network显示边栏  3  另一台机器发送请求控制   找 ...