2009年6月17日 星期三

[LINQ] 初探 LINQ to Objects

哪些類別支援 LINQ 相關功能 ?

LINQ to Objects 表示要透過 LINQ 與集合型態的物件進行互動,這些資料存在於 memory 中,但是 .NET Framework 提供的類別如此之多,支援 LINQ 存取的是哪些呢?

答案就是有實作 System.Collections.IEnumerable 介面的類別所產生的物件都可以

何以見得? 由於 .NET Framework 3.0 以後加入了 Extension Method(擴充方法) 這個機制,且又在 System.Linq.Enumerable 類別中針對實作 System.Collections.IEnumerable 介面的類別加入了許多 Extension Method,而這些類別(Array、List、Dictionary .... 等等)則可說是「自動擴充」成擁有 LINQ 的相關功能。



使用範例

首先是 LINQ to Object Array:

using System;
using System.Linq;

class Program
{
static void Main(string[] args)
{
//定義各種不同型態的資料
Object[] array = { "String", 12, true, 'a' };

var types = array.Select(item => item.GetType().Name) //選取集合中資料的型態
.OrderBy(type => type); //根據型態進行排序

/* 執行結果:
Boolean
Char
Int32
String */
ObjectDumper.Write(types);
Console.ReadLine();
}
}



接著是 LINQ to 自行定義的物件(Book) Array:

using System;
using System.Linq;
using LinqInAction.LinqBooks.Common;

class Program
{
static void Main(string[] args)
{
Book[] books = { new Book { Title = "LINQ In Action" },
new Book { Title = "LINQ For Fun" },
new Book { Title = "Extreme LINQ" } };

var titles = books.Where(book => book.Title.Contains("Action")) //取得 Title 欄位包含 "Action" 關鍵字的書籍資料
.Select(book => book.Title); //取得 Title 欄位

/* 執行結果:
LINQ In Action */
ObjectDumper.Write(titles);
Console.ReadLine();
}
}



其實,只要是 Array,存放於 Array 中可以是任何型態的物件(因為 Array 有實作 System.Collections.IEnumerable 介面)


接著改用 List,除了型態不同以外,query 的方法可說是完全相同:

using System;
using System.Collections.Generic;
using System.Linq;
using LinqInAction.LinqBooks.Common;

class Program
{
static void Main(string[] args)
{
//即使資料換成是 List,LINQ 的語法也是相同的!
List books = new List() { new Book { Title = "LINQ In Action" },
new Book { Title = "LINQ For Fun" },
new Book { Title = "Extreme LINQ" } };

var titles = books.Where(book => book.Title.Contains("Action")) //取得 Title 欄位包含 "Action" 關鍵字的書籍資料
.Select(book => book.Title); //取得 Title 欄位

/* 執行結果:
LINQ In Action */
ObjectDumper.Write(titles);
Console.ReadLine();
}
}



這就是 LINQ 想要達成的目標 => 讓 query 的語言一致!
目前嘗試 Array 與 List 的確有這種感覺~


最後是 LINQ to Dictionary,並用兩種不同的方式(query operator & query expression)進行查詢:

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

class Program
{
static void Main(string[] args)
{
Dictionary myNumbers = new Dictionary();
myNumbers.Add(0, "zero");
myNumbers.Add(1, "One");
myNumbers.Add(2, "Two");
myNumbers.Add(3, "Three");
myNumbers.Add(4, "Four");

//透過 query operator 的方式取得偶數值
var evenNumbers01 = myNumbers.Where(number => number.Key % 2 == 0)
.Select(number => number.Value);
ObjectDumper.Write(evenNumbers01);

//也可以透過 query expression 的方式取得偶數值
var evenNumbers02 = from number in myNumbers
where (number.Key % 2) == 0
select number.Value;
ObjectDumper.Write(evenNumbers02);

/*
以上兩個執行結果都會是:
Zero
Two
Four
*/
Console.ReadLine();
}
}


由此可見,由於 Extend Method 機制的出現,幾乎讓所有集合型態的資料都可以透過 LINQ 的方式進行存取了,只要有實作 System.Collections.IEnumerable 介面即可。

除此之外,查詢的方式也不僅限於一種,除了 query operator 外也還有 query expression 可以使用,甚至兩種同時搭配使用亦可喔!

沒有留言:

張貼留言