C# 初學Lambda表示式
技術標籤:C# Lambda
抄自:https://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html
C# 初學Lambda表示式
一、Lambda 的意義
在Framework 2.0 以前,宣告委託的唯一方法是通過方法命名,從Framework 2.0 起,系統開始支援匿名方法。通過匿名方法,可以直接把一段程式碼繫結給事件,因此減少了例項化委託所需的編碼系統開銷。而在 Framework 3.0 開始,Lambda表示式開始逐漸取代了匿名方法,作為編寫內聯程式碼的首選方式。
二、回顧匿名方法的使用
簡單回顧一下
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
早在Framework 2.0的時候,微軟就為List類添加了Find、FindAll、ForEach等方法用作資料的查詢。
public T Find ( Predicate<T> match)
public List<T> FindAll(Predicate<T> match)
在這些方法中存在一個Predicate 表示式,它是一個返回bool的泛型委託,能接受一個任意型別的物件作為引數。
public delegate bool Predicate<T>(T obj)
在下面例子中,Predicate委託綁定了引數為Person類的方法Match作為查詢條件,然後使用FindAll方法查詢到合適條件的List集合。
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(1, "Hello", 29);
personList.Add(person);
person = new Person(1, "World", 31);
personList.Add(person);
return personList;
}
/// <summary>
/// 查詢條件
/// </summary>
/// <param name="person"></param>
/// <returns></returns>
static bool Match(Person person)
{
return person.Age <= 30;
}
#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 的使用方式與 Predicate 相似,不同之處在於 Predicate 返回值為 bool , Action 的返回值為 void。
Action 支援0~16個引數,可以按需求任意使用。
public delegate void Action()
public delegate void Action (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 泛型委託 Func
static double Account(double a, bool condition)
{
if (condition)
return a * 1.5;
else
return a * 2;
}
#endregion
static void Main(string[] args)
{
#region 泛型委託 Func
Func<double, bool, double> func = Account;
double result = func(1000, 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 = 1000;
Action action = () => x = x + 500;
action.Invoke();
Console.WriteLine($"Result is : {x}");
Console.Read();
#endregion
}
}
執行結果如下:
例子二:通過Action把表示式定義x=x+500,到最後輸入引數1000,得到的結果與例子一相同。
注意,此處Lambda表示式定義的操作使用{ }括弧包括在一起,裡面可以包含一系列的操作。
class Program
{
static void Main(string[] args)
{
#region Lambda例子二
Action<int> action = (x) =>
{
x = x + 500;
Console.WriteLine($"Result is : {x}");
};
action.Invoke(1000);
Console.Read();
#endregion
}
}
執行結果如下:
例子三:定義一個Predicate,當輸入值大約等於1000則返回true,否則返回false。與3.1的例子相比,Predicate的繫結不需要顯式建立一個方法,
而是直接在Lambda表示式裡完成,簡潔方便了不少。
class Program
{
static void Main(string[] args)
{
#region Lambda例子三
Predicate<int> predicate = (x) =>
{
if (x >= 1000)
return true;
else
return false;
};
bool result = predicate.Invoke(500);
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 >= 30)
return price * 0.9;
else
return price;
};
double totalPrice = func(200.0, 40);
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的FindAll方法中直接使用Lambda表示式。相比之下,使用Lambda表示式,不需要定義Predicate物件,也
不需要顯式設定繫結方法,簡化了不工序。
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(1, "Hello", 29);
personList.Add(person);
person = new Person(1, "World", 31);
personList.Add(person);
return personList;
}
/// <summary>
/// 查詢條件
/// </summary>
/// <param name="person"></param>
/// <returns></returns>
static bool Match(Person person)
{
return person.Age <= 30;
}
#endregion
static void Main(string[] args)
{
#region Lambda例子六
List<Person> personList = GetList();
//查詢年齡少於30年的人
List<Person> result = personList.FindAll((person) => person.Age <= 30);
Console.WriteLine("Person count is : " + result.Count);
Console.Read();
#endregion
}
}
執行結果如下:
在使用LINQ技術的時候,到處都會瀰漫著Lambda的身影,此時更能體現Lambda的長處。但LINQ涉及到分部類、分部方法、IEnumerable、迭代器等
多方面的知識,這些已經超出本章的介紹範圍。通過這一節的介紹,希望能夠幫助大家更深入地瞭解Lambda的使用。
轉載自:https://www.cnblogs.com/atomy/p/12080368.html