2009年6月12日 星期五

[C#] delegate(委派) -> Lambda Expression -> LINQ

觀念解說

關於 delegate & Lambda Expression & LINQ 入門,參考以下文章可以得到很清楚的觀念喔!

Huan-Lin 學習筆記: C# 筆記:重訪委派-從 C# 1.0 到 2.0 到 3.0

Huan-Lin 學習筆記: C# 筆記:從 Lambda 表示式到 LINQ

C# 3.0 極簡風 - Lambda Expression - 黑暗執行緒


接著以下只記錄一些瑣碎的筆記........


LINQ 從何而來?

Lambada Expression 大量了使用了之前所提到的 extension method,而 .NET 中也提供了不少的 extension method 以提昇 Lambada Expression 的易用性,藉此讓 LINQ 的語法更加的直覺!

舉例來說,在 System.Linq.Enumerable class 中,就定義了許多 extension method,例如:OrderByDescendingLastMaxMinContainsCount.... 等等。


除了 delegate & Lambda Expression 之外,與 LINQ 有關的特殊功能還有 Implicit typed local variables、Object and collection initializers、Anonymous types 等等。

而除了 delegate 之外,都是在 C# 3.0 中才有提供的(當然 VB.NET 也有),因此看得出來,LINQ 可說是集合所有新功能於一身的查詢技術。


範例說明

以上範例將上述的新功能簡單做了一次完整的結合測試:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace CompleteCode
{
//為了將 Extension Method 定義在此類別, 要加上 static 關鍵字
//否則就要另外定義一個 static class 來放 Extension Method
static class Program
{
static void Main(string[] args)
{
//在呼叫時指定比對用的 function (使用 Lambda Expression)
DisplayProcesses(process => process.WorkingSet64 >= 20 * 1024 * 1024);

Console.ReadLine();
}

//定義 inner class
class ProcessData
{
public Int32 Id { get; set; }
public Int64 Memory { get; set; }
public string Name { get; set; }
}

//此處以委派(delegate)的方式將 match 函式交由呼叫端決定
//傳入的參數型態為 System.Diagnostics.Process
//回傳型態為 Boolean
static void DisplayProcesses(Func match)
{
//此處變數型態會由 compiler 在編譯時決定
var processes = new List();

foreach (var process in Process.GetProcesses())
{
//使用 Object Initializer 的方式宣告物件並給定值
if (match(process))
processes.Add(new ProcessData { Id = process.Id, Name = process.ProcessName, Memory = process.WorkingSet64 });
}

Console.WriteLine("Total memory: {0} MB", processes.TotalMemory() / 1024 / 1024);

//透過 .NET 內建的 Extension Method,取得耗用記憶體最大的兩個 process 所耗費的記憶體總計
var top2Memory = processes.OrderByDescending(process => process.Memory)
.Take(2)
.Sum(process => process.Memory) / 1024 / 1024;
Console.WriteLine("Memory consumed by the two most processes: {0} MB", top2Memory);

//使用 Anonymous Type 宣告物件並顯示
var results = new { TotalMomery = processes.TotalMemory() / 1024 / 1024,
Top2Memory = top2Memory,
Processes = processes };
ObjectDumper.Write(results, 1);
}

//定義 Extension Method(計算記憶體總使用量)
//針對 IEnumerable 型別進行擴充
static Int64 TotalMemory(this IEnumerable processes)
{
Int64 result = 0;

foreach (var process in processes)
result += process.Memory;

return result;
}
}
}

沒有留言:

張貼留言