在本系列文章中會分享Visual Studio 2010的新特性,Visual Studio
2010是微軟的整合開發環境工具,除了有開發環境外,其中更包含了它的核心技術,例如Common Language Runtime
4.0,還有.NET Framework 4.0…等;筆者在剛接觸到Visual Studio
2010後,發覺其中有許多的新技術及觀念值得學習,所以就撰寫了系列文章來介紹。
基礎函式庫加強
在.NET Framework 4.0當中對於基礎的函式庫做了加強了。
BigInteger
.NET Framework 4.0新增了BigInteger的型態,可以用來表達非常大的數字,例如看到以下的程式碼,變數i宣告為BigInteger型態,可以將BigInteger塞進最近的整數值並加以運算。
BigInteger i = new BigInteger(ulong.MaxValue.ToString()); BigInteger iSquared = i.multiply(i); Console.WriteLine("i:\t" + i); Console.WriteLine("i^2:\t" + iSquared); |
結果如下:
i: 18446744073709551615 i^2: 340282366920938463426481119284349108225 |
Tuples
在.NET Framework 4.0當中導入了許多的Functional
Programming的特性,Tuples即是其一,以前我們在撰寫函式時可以傳入許多的參數,但是傳回值只能有一個,運用Tuples可以解決這樣的
問題,Tuples的概念簡單講而言是有限長度的序列,我們可以參考在Wikipedia上的說明:
In mathematics, a tuple is a sequence (or ordered list) of finite length. An n-tuple is a tuple with n elements. Tuples are usually written within parenthesis. For example, (2, 7, 4, 1, 7) is a 5-tuple. |
底下直接來看一個Tuples的範例讓讀者能快速瞭解這個特性:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } public Tuple<int, string> TestTuple() { return new Tuple<int, string>(5, "HelloWorld"); } private void button1_Click(object sender, EventArgs e) { Tuple<int, string> TupleResult = TestTuple(); Console.WriteLine(TupleResult.Item1 + TupleResult.Item2); } } } |
在上面的程式碼當中筆者簡單的在Visual Studio 2010當中新增一個簡單的Windows專案,然後新增一個TestTuple的方法,在這個方法當中運用Tuple型別來傳入泛型參數就可以讓傳回值有多個。
在接收回傳參數可以宣告一個變數來接,然後再用Item1、Item2的方式取得實際的值;或是不用宣告參數直接取得其值,參考程式碼如下:
Console.WriteLine(TestTuple().Item1 + TestTuple().Item2); |
Tuples可以自行實作,但是.NET Framework 4.0的實作相當完整,此特性會是在撰寫.NET Framework的專案時會常用到的特性。
Tuples的使用上雖然便利,可是Tuples的優點也是缺點,雖然可以不用宣告實際的變數型別直接定義型別傳入值就能使用,不過也因為這樣可能會不曉得傳回值的意義。
參考以下的程式碼,假設我們要從一個List當中尋找最大值,以及這個最大值在List當中的索引位置,那麼用Tuples的寫法會是:
Tuple<int,int> void FindMax(List list) |
但是這會讓傳回值不曉得哪一個是MaxValue,哪一個是MaxValue的索引位置,參考以下另外一種寫法,是用傳入參數加入out的修飾詞,也就是傳參考的方式,可以明確知道參數的名稱用途。
void FindMax(List list, out int maxValue, out int maxIndex) |
Records
在C#的說法當中,Record是可以排序的Value Object,所謂的Value Object是單純存放值的物件,而沒有商業邏輯在其中,而在程序式編程當中,Record的概念是繼承至Tuple但可以讓你根據字串來存取項目。
我們看到下面的程式碼,先定義訂單的概念,泛型參數第一個是字串,第二個則是數字;而第二個概念則是客戶的類別,泛型參數第一個是字串,第二個則是訂單列表。
public class Order: Record<string, int> { public Order(string item, int qty): base(item,qty) {} public string Item { get { return state.Item1;}} public int Quantity { get { return state.Item2; } } } public class Customer: Record<string, IEnumerable<Order>> { public Customer(string name, IEnumerable<Order> orders) : base(name, orders) { } public string Name { get { return state.Item1; } } public IEnumerable<Order> Orders { get { return state.Item2; } } } |
Contract特性
在.NET Framework中新增了Contract的語言特性,白話來談就是可以在函式當中指定變數輸入及輸出的條件,對於函式的過程進行更嚴格的檢查;底下看到在Wikipedia當中對於Contract的定義。
A contract is…an exchange of promises between two or more parties to do, or refrain from doing, |
an act which is enforceable in a court of law.- Wikipedia
在程式語言中使用Contract的概念最主要是由Bertrand Meyer所提出來,並且在Eiffel這個語言當中實作,現在在.NET
4.0當中也引進了這項特性,它最大的好處是可以在函式的進行過程中加入許多的Contract來進行檢查,可以大大的減少在實際執行的錯誤。
底下我們直接看到在.NET Framework中對於Contract的支援範例。
Pre-conditions
Pre-conditions可以檢查在執行函式前的條件,例如以下的程式碼確認在函式執行前denominator變數其值要大於0;運用Contract.Requires來進行檢查,Requires就是函式執行前要滿足的條件。
public Rational(int numerator, int denominator) { Contract.Requires(denominator > 0); … } |
Post-conditions
Post-conditions是在函式結束後要滿足的條件,在下面的範例程式當中運用Contract.Ensures來檢查在函式結束後其傳回值一定不能是null。
public string GetPassword() { Contract.Ensures(Contract.Result<string>() != null); … return password; } |
Invariants
Invariants指的是在函式的過程當中永遠不會變的條件,例如以下的範例指的是denominator在函式執行的過程中其值皆要大於0。
[ContractInvariantMethod] protected void ObjectInvariant() { Contract.Invariant(denominator > 0); } |