委派是一種定義方法簽章的型別,隨者 C# 版本的演變,它的使用方法也有些許的變化。 例如:具名方法,匿名方法,Lambda表示法。
委派宣告
不同的 C# 版本,委派的宣告方法還是一樣的,不同的是委派的使用方法。
存取型態 delegate 回傳值型別 delegateName ( [參數列] )
使用具名委派
// 定義一個委派
public delegate bool MyDelegate(Employee e);
// 定義一個方法,找出大於40歲的人
private Boolean IsElder40(Employee emp)
{
return emp.Age > 40;
}
public void button2_Click(object sender, EventArgs e)
{
List<Employee> empList = new List<Employee>(){
new Employee{Name="apple21",Age=21},
new Employee{Name="dean51", Age=51},
new Employee{Name="carry41",Age=41},
new Employee{Name="book31", Age=31}
};
//實體化一個委派,並具名的指出要執行的方法
MyDelegate myDelegate = new MyDelegate(IsElder40);
//上一行也可以這麼寫
//MyDelegate myDelegate = IsElder40;
//==================================================================
//將List中的每一個成員,都送給委派所指定的方法去執行,以驗證結果
//==================================================================
foreach (Employee emp in empList)
{
//Invoke 委派
bool result = myDelegate.Invoke(emp);
//上一行也可以這麼寫
//bool result = myDelegate(emp);
Console.WriteLine(result); // F T T F
}
//==================================================================
//List.FindAll(Predicate<T>)
//FindAll的參數是一個系統內部定義的泛型委派 Predicate<T> ,
//Predicate<T> 要求傳入一個物件,會回傳一個 bool,剛好我們的 IsElder40 符合這個要求。
//==================================================================
List<Employee> empFindResult = empList.FindAll(IsElder40);
foreach (Employee emp in empFindResult) // dean51 carry41
Console.WriteLine(emp.Name);
}
上面這個例子,List<T> 的 FindAll 這個方法,接受一個 Predicate<T> 的泛型委派,所以可以傳入我們定義的 IsElder40 這個方法。
委派的演變
//定義一個委派
public delegate bool MyDelegate(Employee e);
Employee emp1 = new Employee("vito", 25);
//==================================================================================
// 1.0) 具名委派
//==================================================================================
MyDelegate d1 = new MyDelegate(IsElder40);
d1(emp1);
//==================================================================================
// 2.0) 匿名委派
//==================================================================================
MyDelegate d2 = delegate(Employee emp)
{
return emp.Age > 40;
};
d2(emp1);
//==================================================================================
// 3.0) 匿名委派 轉 Lambda
//==================================================================================
MyDelegate d3 = (Employee emp) =>
{
return emp.Age > 40;
};
d3(emp1);
// 因為只有一行,可以去掉大括弧和 return
MyDelegate d4 = (Employee emp) =>
emp.Age > 40;
d4(emp1);
// 符合泛型委派 Predicate<T> 的定義,所以就用 Predicate<T>
Predicate<Employee> d5 = (Employee emp) =>
emp.Age > 40;
d5(emp1);
// 因為參數列只有一個,編譯器可從委派定義得知型別,所以可以把小括弧和型別名稱都去掉
Predicate<Employee> d6 = emp =>
emp.Age > 40;
d6(emp1);
// 最後再精簡一下變數符號,就成底下這樣了
// 所以 p 就是一個泛型委派的實體
Predicate<Employee> p = e => e.Age > 40;
從 Lambda 表示式到 LINQ
List<Employee> empList = new List<Employee>(){
new Employee{Name="apple21",Age=21},
new Employee{Name="dean51",Age=51},
new Employee{Name="carry41",Age=41},
new Employee{Name="book31",Age=31}
};
//使用 Lambda 表示式,定義一個泛型委派
Predicate<Employee> p1 = e => e.Age > 40;
//找第一個符合委派方法的項目
Employee emp1 = empList.Find(p1);
//若只要叫用一次,換成這樣寫,可以比較彈性了
Employee emp2 = empList.Find(e => e.Age > 40);
//也可以變換判斷規則
Employee emp3 = empList.Find(e => e.Age > 50); //回傳第一個大於50歲的人
Employee emp4 = empList.Find(e => e.Name.Contains("a")); //回傳第一個名字中含a的人
//==================================================================================
//使用 List<T> 的 FindAll 方法查詢所有符合條件的資料,回傳型別是 List<T>,接受參數是泛型委派 Predicate<T>
//==================================================================================
List<Employee> result1 = empList.FindAll(e => e.Name.Contains("a"));
//==================================================================================
//改用 List<T> 的 Where 這個擴充方法查詢資料,回傳型別是 IEnumerable<T>,但接受參數是另一個泛型委派 Func<T, R>
//==================================================================================
IEnumerable<Employee> result2 = empList.Where<Employee>(e => e.Name.Contains("a"));
//==================================================================================
//搭配 OrderBy , Select 等擴充方法,這二個方法也都接 Func<T, R> 型別的參數,最後 Select 回傳型別是 IEnumerable<string>
//==================================================================================
IEnumerable<string> result3 = empList
.Where<Employee>(e => e.Name.Contains("a"))
.OrderBy<Employee,int>(e => e.Age)
.Select<Employee, string>(e => e.Name);
//改用 LINQ 表示式來對照,
IEnumerable<string> result4 = from e in empList
where e.Name.Contains("a")
orderby e.Age
select e.Name;
//為方便起見,回傳型別宣告成 var 隱含型別。
var names = from e in empList
where e.Name.Contains("a")
orderby e.Age
select e.Name;

沒有留言:
張貼留言