C#学习笔记 Lambda表达式

在委托实例化时,总要使用一个函数,所以我们去单独定义一个函数,但是在更多的时候,我们不想这样做,而是直接定义函数、直接使用,这时可以使用匿名函数或Lambda表达式,它们分别是C#2.0 和C#3.0 中引入的。

Lambda表达式

Lambda表达式(或者叫λ表达式),实际上是直接写函数头和函数体,而不写函数名,在函数头和函数体之前用符号 => 来表示。并且将这个函数直接赋给一个委托或作为另一个函数的参数。例如:

	MyDelegate d = (double x) => {
    
     return x + 5; };
	MyDelegate d = new MyDelegate((double x) => {
    
     return x + 5; });

由于Lambda表达式总是与委托类型兼容,其类型可以由编译器来自动推断,所以可以省略参数的类型,只写参数变量的名字。例如:

	MyDelegate d = (x) => {
    
     return x + 5; };

如果只有一个参数,参数的圆括号也是可以省略的。如果只有一个返回表达式或一条语句,函数的花括号也是可以省略的。例如:

	MyDelegate d = x => {
    
     return x + 5; };
	Mydelegate d = x => x + 5;

在函数的数值积分中,可以将Delegate用Lambda表达式来书写:

	result = Intergral(x => 2 * x + 1, 0, 1, 0.01);
	result = Intergral(x => Math.Sin(x), 0, Math.PI, 0.01);

可以说,Lambda表达式就是一个内嵌函数,更准确地说是一个内嵌的委托变量。

匿名函数

匿名函数就是没有名字的函数,在定义函数的同时如果马上赋值给委托,所以不需要名字,或者说由编译器来自动生成名字。为了表示它是一个匿名函数,前面要加一个关键字delegate。例如:

	MyDelegate d = delegate (double x){
    
     return x + 5; }; 

这里需要注意的是:delegate在这里表示匿名函数,虽然delegate这个词也可以用来定义委托类型,但编译器是不会混淆的。
可见,匿名函数与Lambda表达式是差不多的,只不过匿名函数使用delegate来表示,而Lambda表达式使用 => 来表示。由于Lambda可以省略的更多,所以现在很少用匿名函数了。
如果说匿名函数有一个用途的话,那就是匿名函数不用写参数类型及参数名,如:

	MyDelegate d = delegate {
    
     return 100; };

不过,用Lambda表达式也并不麻烦:

	MyDelegate d = x => 100;

属性、索引器的简写

Lambda表达式(以及匿名函数)不仅可以简化函数调用时的参数的书写,在C#6.0 以上版本中,还可以简化方法、属性、索引器等成员的定义,称为“表达式体成员”(expression bodied members)。例如:

	public double Square(double n) => n * n;		// 方法
	public double Dist => Math.Sqrt(X * X + Y * Y);	// 只读属性
	public int this[int a] => members[a];			// 只读索引器

第1句和第2句分别定义了属性和方法(只有get,没有set)。
在C#7.0 以上版本中,还可以在构造方法、set属性等更多的运用“表达式体成员”,如:

	public Person(string name) => names.TryAdd(id, name);
	public string Name{
    
    
		get => names[id];				// getters
		set => names[id] = value;		// setters
	}

3个示例程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

class Program
{
    
    
	static void Main(string[] args) {
    
    
		Console.WriteLine("Hello World!");
		Example2();
		Console.WriteLine("---------------------分割线---------------------");
		Example3();
	}

	// 示例1, 使用线程
	private void Example1() {
    
    
		// csharp 1.0
		// 使用委托,使用已定义好的函数
		new Thread(new ThreadStart(MyFun)).Start();

		// csharp 2.0
		// 省略委托:MyFun自动实例化为ThreadStart委托
		new Thread(MyFun).Start();
		// 匿名方法
		new Thread(new ThreadStart(delegate () {
    
     Console.WriteLine("my function"); })).Start();
		// 匿名方法, 省略参数列表
		new Thread(new ThreadStart(delegate {
    
     Console.WriteLine("my function"); })).Start();
		// 匿名方法, 自动转委托
		new Thread(delegate () {
    
     Console.WriteLine("my function"); }).Start();

		// csharp 3.0
		// Lambda表达式
		new Thread(() => {
    
     Console.WriteLine("my function"); }).Start();
	}
	private void MyFun() {
    
    
		Console.WriteLine("my function");
	}


	// 示例2, 使用事件
	public class TestEventArgs
	{
    
        // 事件数据
		public string name;
		public TestEventArgs(string name) {
    
     this.name = name; }
	}
	public delegate void TestHandler(object sender, TestEventArgs e);    // 1.声明委托, 公用的
	public class TestEvent
	{
    
    
		public event TestHandler Test;  // 2.声明事件, 在一个类中
		public void UseTestEvent() {
    
     Test(this, new TestEventArgs("name")); }    // 调用事件Test
	}
	private static void Example2() {
    
    
		TestEvent testEvent = new TestEvent();

		// csharp 1.0
		// 使用委托, 使用自定义函数
		testEvent.Test += new TestHandler(TestEvent_Test);   // 3.在别的类中注册事件

		// csharp 2.0
		// 自动转委托
		testEvent.Test += TestEvent_Test;
		// 匿名方法
		testEvent.Test += new TestHandler(delegate (object sender, TestEventArgs e) {
    
     Console.WriteLine("TestEvent_Test " + e.name); });
		// 匿名方法, 自动转委托
		testEvent.Test += delegate (object sender, TestEventArgs e) {
    
     Console.WriteLine("TestEvent_Test " + e.name); };

		// csharp 3.0
		// 使用Lambda表达式
		testEvent.Test += (object sender, TestEventArgs e) => {
    
     Console.WriteLine("TestEvent_Test " + e.name); };
		testEvent.Test += (sender, e) => {
    
     Console.WriteLine("TestEvent_Test " + e.name); };

		testEvent.UseTestEvent();
	}
	private static void TestEvent_Test(object sender, TestEventArgs e) {
    
    
		Console.WriteLine("TestEvent_Test " + e.name);
	}


	// 示例3, 数组排序
	class Book
	{
    
    
		public string title;
		public double price;
		public Book(string title, double price) {
    
     this.title = title; this.price = price; }
	}
	private static void Example3() {
    
    
		Random rnd = new Random();
		Book[] books = new Book[10];
		for (int i = 0; i < books.Length; i++) books[i] = new Book("Book" + i, rnd.Next(100));
		foreach (Book book in books) Console.WriteLine(book.title + " " + book.price);
		Console.WriteLine();

		// csharp 1.0
		Array.Sort(books, new MyComparer());

		// csharp 2.0
		// 使用Comparison委托
		Array.Sort<Book>(books, new Comparison<Book>(delegate (Book book1, Book book2) {
    
     return (int)(book1.price - book2.price); }));
		Array.Sort<Book>(books, delegate (Book book1, Book book2) {
    
     return (int)(book1.price - book2.price); });

		// csharp 3.0
		Array.Sort<Book>(books, (Book book1, Book book2) => (int)(book1.price - book2.price));
		Array.Sort<Book>(books, (book1, book2) => (int)(book1.price - book2.price));   //省略参数类型

		foreach (Book book in books) Console.WriteLine(book.title + " " + book.price);


		// 使用Linq
		IOrderedEnumerable<Book> result = from book in books orderby book.price select book;

		var result1 = from book in books where book.price >= 0 orderby book.price select book.title;
		foreach (string s in result1) Console.WriteLine(s);

		var result2 = books
			.Where<Book>(b => b.price >= 0)
			.OrderBy<Book, double>(b => b.price, Comparer<double>.Default)
			.Select<Book, Book>(book => book);
		foreach (Book b in result2) Console.WriteLine(b.price + " ");

	}
	class MyComparer : System.Collections.IComparer
	{
    
    
		public int Compare(object x, object y) {
    
    
			return (int)(((Book)x).price - ((Book)y).price);
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_45349225/article/details/114089860