C# 3.0

來源:互聯網
上載者:User

 1, Implicitly typed local variables(隱式類型的局部變數)引入 var 關鍵字,容許變數類型從代碼上下文中引出:
var n = 10;
var f = 10.0;
var a = new int [] {1,2,3,4};
int [] ns = {1,2,3,4,5};
foreach(var v in ns)
當然C# 仍然是強型別的,如果發現類型無法判斷,那麼還是會編譯時間報錯,var s = null; // 編譯錯誤,因為無法根據null知道 s 是什麼類型這個沒什麼好解釋的,是個人都知道這是什麼意思
2. Extension Method (擴充方法)
容許對存在的類型添加方法(相當於2.0中的partial class)但是現在即使你原來沒有申明 partial 屬性, 這樣的類你也可以給它添加方法了,下面是例子:
首先要建立一個靜態類, 給它添加一些靜態方法但是最重要的是第一個參數是 this 開頭namespace Acme.Utilities
{
    public static class Extensions
    {
        public static int ToInt32(this string s) {
            return Int32.Parse(s);
        }
        public static T[] Slice<T>(this T[] source, int index, int count) {
            if (index < 0 || count < 0 || source.Length - index < count)
                throw new ArgumentException();
            T[] result = new T[count];
            Array.Copy(source, index, result, 0, count);
            return result;
        }
    }
}
這樣當你使用時, using Acme.Utilities;
這時這個包中所有的"擴充方法"都會被合并到當前的類型中比方,對於 string 類型的, 就相當於存在一個 String.ToInt32() 這樣一個方法了而對於 T[] 類型的,就存在一個 T[].Slice(int index, int count) 這樣的方法(注意這裡 T[] 是一個模版類型,如果類型有條件不知道該怎麼聲明了)
using Acme.Utilities;
string s = "1234";
int i = s.ToInt32(); // 相當於調用了 Same as Extensions.ToInt32(s)
int[] digits = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int[] a = digits.Slice(4, 3); // 相當於調用了 Extensions.Slice(digits, 4, 3)
3.Lambda Expression(λ運算式) 引入了 => 操作符
C# 2.0 中引入了匿名函數,容許內嵌寫委託函數, 但是還是稍嫌複雜而 λ運算式 可以讓這個"使用"(請注意是使用)變得簡潔得多,它的文法基本如下 : (參數) => 運算式, 或者 參數 => 運算式,具體大家可以看 那篇文檔中的文法. 下面是例子
(int x) => { return x + 1; }
(x, y) => x * y
() => Console.WriteLine()
看實際應用:
namespace System.Query
{
    public static class Sequence
    {
        public static IEnumerable<S> Select<T,S>(
            this IEnumerable<T> source,
            Func<T,S> selector)
        {
            foreach (T element in source) yield return selector(element);
        }
    }
}
這裡定義了一個擴充方法,給 IEnumerable<T>類型 加了一個 Select 方法這個方法需要一個 delegate Func<T, S> selector 以便對 IEnumerable<T> 中每個元素都執行 Func<T,S>() 操作, 並且返回了 Func<T,S>() 這個操作的結果如果你比較熟悉 STL ,那麼這個和其中的 for_each 演算法是比較相像的現在看怎麼調用這個方法:
List<Customer> customers = GetCustomerList();
IEnumerable<string> names = customers.Select(c => c.Name);
這樣我們看到 c => c.Name 規則 就變成了 delegate Func<T,S> selector
從而 selector 就對應於 string select(Customer c) { return c.Name; }
也就是對每個 Customer, 取得他的 Name 值關於上面的代碼綜合運用了 "隱式類型", "模版方法" "擴充方法", 和 (λ運算式)如果你看不懂屬於正常, 其實 (λ運算式) 真正強在於能自動根據代碼上下文匹配到對應的模版方法, 再來看一個例子:
static Z F<X,Y,Z>(X value, Func<X,Y> f1, Func<Y,Z> f2) {
    return f2(f1(value));
}
double seconds = F("1:15:30", s => TimeSpan.Parse(s), t => t.TotalSeconds);
從上面, C# 編譯器能自動知道 "1:15:30" 是 string類型,傳回值是 double 類型於是 Z 對應 double, X 對應 string, 而 s => TimeSpan.Parse(s) 可以知道 s 是 string 類型, 返回 TimeSpan於是 Func<X, Y> f1 應當是函數 TimeSpan f1(string s); X 對應 string, 於是 Y 對應TimeSpan同理,由t => t.TotalSeconds 知道 double f2(TimeSpan), Y 對應 TimeSpan, Z 對應double所以當 使用 double seconds = F("1:15:30", s => TimeSpan.Parse(s), t => t.TotalSeconds);時,那個 F 函數就被翻譯成了static double F(string value,
TimeSpan f1(string s){ return TimeSpan.Parse(s); },
double f2(TimeSpan) { return TimeSpan.TotalSeconds; } );看到了吧, 極其強大, 使用也極其簡潔, 但後面隱藏的規則也極其複雜如果真有這樣複雜的函數,我不知道會有多少人能夠理解 :)這裡我跳過了一些關於函數重載時,(λ運算式)的內部如何匹配的處理規則,請看原文
4.Object and collection initializer(對象和集合的初始化代碼塊)就是讓你在 new 對象時,可以同時初始化對象的一些屬性,看看例子就明白了,先看對象的初始化
ublic class Point
{
    int x, y;
    public int X { get { return x; } set { x = value; } }
    public int Y { get { return y; } set { y = value; } }
}
var a = new Point { X = 0, Y = 1 }; // 後面{}裡的內容就是我們說的初始化代碼塊這個和先建立 Point, 然後分別設定 X,Y屬性是一樣的,就是稍微簡潔了點var a = new Point(); a.X = 0; a.Y = 1;真正重要的是集合的初始化代碼塊, 因為你要知道,在以前C# 1/2 是無法在初始化一個集合/數組時初始化好每個元素的屬性的(如果這些屬性不被包括在建構函式中的話)但是現在有了對象的初始化代碼塊, 現在就可以了, 例子:
List<Point> line = new List<Point>
{ new Point {X = 1,Y =1}, new Point {X = 10, Y=10} };
而這個在以前是無法完成的, 除非 Point 有一個建構函式 Point(int x, int y);
5.Anonymous Types(匿名型別)
靠,C#越來越變得指令碼化了, 現在你不用再像以前那樣先寫好一個class,然後再來用了, 而是直接把class的代碼寫在對象的初始化代碼塊中, 看例子:
var p1 = new { Name = "Lawnmower", Price = 495.00 };
上面等於定義了一個類型, 具有 Name, Price 成員欄位目前好像只能支援 Field / Property,無法在裡面加方法當然如果你定義了兩個相同的匿名型別, C# 還是會比較智能的合并的
var p2 = new { Name = "Shovel", Price = 26.95 };
p1 = p2;
6.Implicitly typed arrays(隱式類型數組)
就是建立數組時讓編譯器自動判斷數群組類型
var a = new []{1,2,3,4}; // 這個就相當於 int [] a = new int[]{1,2,3,4};
var b = new []{"r", "g", "b"}; // 相當於建立了一個字串數組
7.Query Expression(查詢運算式)
重要的來了 :), 這個應當是 C# 整合了那個 LINQ項目的結果,不過一路看下來,發現前面所有的工作都是為了這個目的如果有誰寫過大型主機上的資料庫程式,估計對代碼中嵌入SQL都不會太陌生,比方 SQL-C不過MS讓這個又更進了一步,讓QUERY同時支援了XML資料和SQL查詢以及運算式並且和 代碼無縫整合, 果然有夠強具體文法還是請大家看原文,大致的文法如下:from 標誌符 in 運算式(,標誌符 in 運算式(,...)) where 條件 orderby 排序運算式 (group 運算式 by 運算式) 或者 (select 運算式)into 標誌符基本上和 SQL 陳述式一樣, 只是 select 語句在後面但是真正有意思的是C# 本身是不處理這個查詢運算式如何執行而是把它轉換成了對每個運算式Where,Select,SelectMany,OrderBy,GroupBy等這樣的方法的調用, 比方你寫了
from c in customers where c.City = "London" select c.Name那麼對於這裡的where 和 select 語句的處理就被轉換成了函數調用customers.Where(c => c.City = "London").Select(c => c.Name);這樣前面提到的 λ運算式 和 擴充方法 就發揮作用了.只要你的customers 對象存在擴充方法 Where,或者一般的方法Where並且Where返回的結果支援方法 Select, 那麼這個查詢就可以執行而根本不在乎你的customers是XML還是資料庫的表, 而且由於可以使用 擴充方法 , 你只要到時候添加一個實現了 Where,Select這些擴充方法的函數包,就可以讓需要的資料類型支援這種 查詢運算式再看一些其他例子:
from c in customers group c.Name by c.Country
轉換成 customers.GroupBy(c => c.Country, c=>c.Name);from c in customers orderby c.Name select new {c.Name, c.Phone};轉換成 customers.OrderBy(c => c.Name).Select(c => new {c.Name, c.Phone});
再看一個嵌套的查詢
from c in customers where c.City == "London"
from o in c.Orders where o.OrderDate.Year == 2005
select new { c.Name, o.OrderID, o.Total }
轉換成
customers.
Where(c => c.City == "London").
SelectMany(c =>
c.Orders.
Where(o => o.OrderDate.Year == 2005).
Select(o => new { c.Name, o.OrderID, o.Total })
);
可以預見,到時候 .Net Framework 必定會附帶一個 System.Query.dll
裡面實現了絕大部分Collection, Xml, Database這些對象的
Where/Select 這些 擴充方法 以支援查詢運算式
8.Expression trees(運算式樹狀架構)
這個原文中沒有做過多的介紹,裡面說還有一篇文檔是專門介紹這個主題的基本大意是對於 λ運算式
Func<int,int> f = x => x + 1; // Code可以使用 System.Query中的一個模版類 Expression<D> 把運算式轉成資料Expression<Func<int,int>> e = x => x + 1; // Data也就是對於 f 這個其實是一個可以啟動並執行代碼,執行 x = x+1;
對於 e, 則是一個描述代碼 f 的一個資料結構!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.