[C#.NET/Linq]LINQ新特性簡介及入門教程

 LINQ 使查詢成爲了.NET中頭等的編程概念,被查詢的數據可以是XML(LINQ to XML)、Databases(LINQ to SQL、LINQ to Dataset、LINQ to Entities)和對象(LINQ to Objects)。LINQ也是可擴展的,允許你建立自定義的LINQ數據提供者(比如:LINQ to Amazon、LINQ to NHibernate、LINQ to LDAP)。在這裏我會討論C#3.0中的一些新的語言特性和改進,正是它們使得LINQ變得如此強大~~


翻譯

Amro KhasawnehUnderstanding LINQ (C#)
flanker譯(還請指教啊)

簡介

 

 

本 文主要是關注於LINQ——我認爲是VS2008(.NET3.5)中最令人興奮的特性。LINQ使查詢成爲了.NET中頭等的編程概念,被查詢的數據可 以是XML(LINQ to XML)、Databases(LINQ to SQL、LINQ to Dataset、LINQ to Entities)和對象(LINQ to Objects)。LINQ也是可擴展的,允許你建立自定義的LINQ數據提供者(比如:LINQ to Amazon、LINQ to NHibernate、LINQ to LDAP)。

在這裏我會討論C#3.0中的一些新的語言特性和改進,正是它們使得LINQ變得如此強大,讓你可以寫出這樣的代碼:

var result = from c in
 Customers
where c.City == Boston"
orderby c.LastName descending
select new { c.FirstName, c.LastName, c.Address };

記住,如果你想要使用LINQ,你需要安裝Visual Studio 2008(.NET3.5)。

新的語言特性

I/ 自動屬性

public
 class
 Point {
private int _x, _y;
public int X {
get { return _x; }
set { _x = value; }
}
public int Y {
get { return _y; }
set { _y = value; }
}
}

上面的代碼簡單的定義了一個擁有兩個屬性的類。現在,使用VS2008中的C#編譯器,我們就可以用自動屬性寫的更簡單,它能自動的生成帶有get /set 操作的私有域。

public
 class
 Point {
public int X { get; set; }
public int Y { get; set; }
}

上面的代碼可讀性更好並且簡潔。
(這個特性和LINQ還沒有關係)

II/ 局部變量類型

使用這個特性,聲明一個局部變量,它的具體類型是通過初始化表達式來推斷。這點是通過var 關鍵詞完成的(這個使用腳本語言的人應該很熟悉,但它們實際上是有很大區別的)。我們可以寫出如下的代碼:

var num = 50;
var str = "simple string" ;
var obj = new myType();
var numbers = new int [] {1,2,3};
var dic = new Dictionary<int ,myType>();

編譯器會生成IL中間代碼,就如同我們編譯了下面的代碼:

int
 num = 50;
string str = "simple string" ;
myType obj = new myType();
int [] numbers = new int [] {1,2,3};
Dictionary<int ,myType> dic = new Dictionary<int ,myType>();

注意,這裏並不存在無類型的變量,也沒有推遲類型的綁定。編譯器是從右邊的賦值語句來自動推斷和聲明變量的類型的,var 關鍵詞是一個強類型的變量引用。

III/ 對象初始化和集合初始化

我們繼續使用上面的Point 類。假設我們想要這個類的一個實例,我們會建立對象並設置它的屬性,代碼會是這樣子的:

Point p = new
 Point();
p.X = 0;
p.Y = 0;

現在,使用對象初始化,就可以像這樣子來重寫:

Point p = new
 Point() { X = 0, Y = 0 };

這個特性也可以使用在集合上,看看下面這段示例:

List points = new
 List {
new Point { X = 2, Y = 5 },
new Point { X = 1, Y = -10 },
new Point { X = 3, Y = 0 }
};

注意,編譯器會產生和上面相等價的長一些的代碼,它依次調用Add() 方法來在集合裏添加元素。

IV/ 匿名類型

這個語言特性讓我們可以定義內嵌的類型,而不需要顯式地定義一個類型。換句話說,假設我們沒有定義Point 類,卻要使用一個Point 對象(即類型是匿名的)。我們可以使用上面提到的對象初始化語法,但不用指定類型名:

var p = new
 {X = 0, Y = 2};

在VS2008中,你仍然可以使用智能感應。所以如果你繼續使用變量p,就會得到這個匿名類型的屬性列表。

V/ Lambda表達式

在 C#2.0中引入了匿名方法,允許在需要委託的地方寫一個代碼塊。匿名方法提供了函數式程序語言的能力,語法顯得很簡潔。Lambda表達式提供了一個更 簡潔的語法來寫匿名方法。一個Lambda表達式就是一個參數列表(可以隱式類型),然後是一個=>符號,然後是一個表達式或者一個語句塊。

作爲一個示例,我們定義一個委託類型MyDeleg

delegate
 R MyDeleg(A arg);

然後我們就可以使用匿名方法:

MyDeleg<int
,bool
> IsPositive = delegate
(int
 num) {
return num > 0;
};

我們也可以使用新的Lambda表達式來寫:

MyDeleg<int
,bool
> IsPositive = num => num > 0;

VI/ 擴展方法

擴展方法可以使你來擴展一個已存在的類型,增加它的方法,而無需繼承它或者重新編譯。所以不像爲對象寫助手方法,擴展方法可以直接是對象自己的一部分。

一個示例,假設我們想要驗證一個string 是不是合法的Email地址,我們可以編寫一個方法,輸入爲一個string 並且返回true 或者false 。現在,使用擴展方法,我們可以如下這樣做:

public
 static class
 MyExtensions {
public static bool IsValidEmailAddress(this string s) {
Regex regex = new Regex( @"^[w-.]+@([w-]+.)+[w-]{2,4}$" );
return regex.IsMatch(s);
}
}

我們定義了一個帶有靜態方法的靜態類。注意,那個靜態方法在參數類型string 前面有一個this 關鍵詞,這會告訴編譯器這個特殊的擴展方法會增加給string 類型的對象。於是我們就可以在string 中調用這個成員方法:

using
 MyExtensions;

string email = Request.QueryString["email" ];
if ( email.IsValidEmailAddress() ) {
// ...
}

值得提出的是,LINQ就是使用了System.Linq 命名空間中的擴展方法(比如where()、orderby()、select()、sum()、average()等等),而且它定義了標準查詢操作符,可以用來查詢關係數據庫、XML和任何實現了IEnumerable<T> 接口的.NET對象。

VII/ 查詢語法

查詢表達式提供了一個語言集成的語法來查詢,它特別像關係和層次查詢語言比如SQL和XQuery。使用LINQ操作符(也就是from...where...select)寫查詢很方便,Visual Studio爲它提供了很好的智能感知和編譯時的檢查支持。
當C#編譯器遇到了一個查詢語法表達式時,實際上它會被轉化爲使用擴展方法和Lambda表達式的方法調用。

我們舉一個例子來解釋這個:

var result = from c in
 Customers
where c.City.StartsWith("B" )
orderby c.LastName
select new { c.FirstName, c.LastName, c.Address };

上面的代碼等價於:

var result = Customers.Where( c => c.City.StartsWith("B"
) )
.OrderBy( c => c.LastName )
.Select( c => new { c.FirstName, c.LastName, c.Address } );

使用查詢語法的好處還有它會使代碼更簡單更易讀。
同時注意,查詢表達式以from 開頭,以select 或者group 結尾。

最後注意

C#3.0中新引入的幾個特性大多數都僅僅是“編譯器技巧”或者“語法糖”,其實編譯器生成的IL中間代碼和原來的是一樣的,這樣他們就獨立於framework和CLR運行時。但是,他們確實需要某些framework的支持,比如System.Core.dll 程序集。這就是爲什麼擴展方法仍然需要依靠於System.Core.dll 裏包含的System.Runtime.CompilerServices.ExtensionAttribute
另一方面,查詢表達式只是實現了到擴展方法的映射,它包含在System.Linq, System.Data.LinqSystem.Xml.Linq 命名空間中。

參考和資源

 

"New Orcas Language Feature" Series by Scott Guthrie : 講解LINQ的系列文章 LINQ Resources : Daniel Moth 寫的日誌 MSDN Magazine (June 2007) : 一篇介紹 C# 3.0 和 LINQ 的文章 Visual Studio Orcas Samples : C#/VB LINQ 示例 Future Versions : C# 3.0 The LINQ Project : LINQ 項目主頁
發佈了42 篇原創文章 · 獲贊 3 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章