[翻譯]C#3.0與LINQ新特性簡介

來源:互聯網
上載者:User
翻譯
Amro Khasawneh 著 Understanding LINQ (C#)
flankerfc 譯 in MSProject

簡介


本文主要是關注於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.Linq和System.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 項目首頁   

     

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.