c# 4.0新特性一覽

來源:互聯網
上載者:User

終於靜下心來仔細聽了一遍Anders Hejlsberg(Visual Studio組的TECHNICAL FELLOW,C#的設計者之一)在PDC08上講的“The Future of C#”(http://channel9.msdn.com/pdc2008/TL16/)。

回顧C#發展的曆史,C#1.0完全是模仿Java,並保留了C/C++的一些特性如struct,新學者很容易上手;C#2.0加入了泛型,也與Java1.5的泛型如出一轍;C#3.0加入了一堆文法糖,並在沒有修改CLR的情況下引入了Linq,簡直是神來之筆,雖然很多項目出於各種各樣如效能之類的原因沒有採用,但非常適合小型程式的快速開發,減輕了程式員的工作量,也提高了代碼的可讀性;C#4.0增加了動態語言的特性,從裡面可以看到很多javascript、python這些動態語言的影子。雖然越來越偏離靜態語言的道路,但從另一個角度來說,這些特性也都是為了提高程式員的生產力。至於被接受與否,還是讓時間來說話吧。

PS:這裡面還有一點版本號碼的小插曲——VS2008所對應的.Net Framework是3.5,C#是3.0,CLR是2.0,及其混亂,MS終於下決心在VS2010中把這三個版本號碼都統一成了4.0,於是CLR3不知所終……

Dynamically Typed Object

C#4.0加入了dynamic關鍵字,可以申明一個變數的static類型為dynamic(有點繞口)。

在3.0及之前,如果你不知道一個變數的類型,而要去調用它的一個方法,一般會用到反射:

object calc = GetCalculator();Type calcType = calc.GetType();object res = calcType.InvokeMember("Add",BindingFlags.InvokeMethod, null,new object[] { 10, 20 });int sum = Convert.ToInt32(res);

有了dynamic,就可以把上面代碼簡化為:

dynamic calc = GetCalculator();int sum = calc.Add(10, 20);

使用dynamic的好處在於,可以不去關心對象是來源於COM, IronPython, HTML DOM或者反射,只要知道有什麼方法可以調用就可以了,剩下的工作可以留給runtime。下面是調用IronPython類的例子:

ScriptRuntime py = Python.CreateRuntime();dynamic helloworld = py.UseFile("helloworld.py");Console.WriteLine("helloworld.py loaded!");
dynamic也可以用在變數的傳遞中,runtime會自動選擇一個最匹配的overload方法。

這裡有一個demo:把一段javascript代碼拷到C#檔案中,將var改成dynamic,function改成void,再改一下建構函式的調用方式(new type()改為win.New.type()),去掉javascript中的win.首碼(因為這已經是C#的方法了),就可以直接運行了。

dynamic的實現是基於IDynamicObject介面和DynamicObject抽象類別。而動態方法、屬性的調用都被轉為了GetMember、Invoke等方法的調用。

public abstract class DynamicObject : IDynamicObject{public virtual object GetMember(GetMemberBinder info);public virtual object SetMember(SetMemberBinder info, object value);public virtual object DeleteMember(DeleteMemberBinder info);   public virtual object UnaryOperation(UnaryOperationBinder info);public virtual object BinaryOperation(BinaryOperationBinder info, object arg);public virtual object Convert(ConvertBinder info);   public virtual object Invoke(InvokeBinder info, object[] args);public virtual object InvokeMember(InvokeMemberBinder info, object[] args);public virtual object CreateInstance(CreateInstanceBinder info, object[] args);   public virtual object GetIndex(GetIndexBinder info, object[] indices);public virtual object SetIndex(SetIndexBinder info, object[] indices, object value);public virtual object DeleteIndex(DeleteIndexBinder info, object[] indices);   public MetaObject IDynamicObject.GetMetaObject();}

 

Named and optional parameters

這似乎不是什麼很難實現或很新穎的特性,只要編譯器的支援就可以(VB很早就支援了)。估計加入的原因是群眾的呼聲太高了。

帶有選擇性參數方法的聲明:

public StreamReader OpenTextFile(string path,Encoding encoding = null,bool detectEncoding = true,int bufferSize = 1024);

具名引數必須在最後使用:

OpenTextFile("foo.txt", Encoding.UTF8, bufferSize: 4096);

順序不限:

OpenTextFile(bufferSize: 4096, path: "foo.txt", detectEncoding: false);
Improved COM Interoperability

在C#中在調用COM對象如office對象時,經常需要寫一堆不必要的參數:

object fileName = "Test.docx";object missing  = System.Reflection.Missing.Value;doc.SaveAs(ref fileName,ref missing, ref missing, ref missing,ref missing, ref missing, ref missing,ref missing, ref missing, ref missing,ref missing, ref missing, ref missing,ref missing, ref missing, ref missing);

4.0中就可以直接寫成:

doc.SaveAs("Test.docx");

C#4.0對COM互動做了下面幾方面的改進:

  1. Automatic object -> dynamic mapping
  2. Optional and named parameters
  3. Indexed properties
  4. Optional “ref” modifier
  5. Interop type embedding (“No PIA”)

對第1點和第5點的簡單解釋如下:

在COM調用中,很多輸入輸出類型都是object,這樣就必須知道返回對象的確切類型,強制轉換後才可以調用相應的方法。在4.0中有了dynamic的支援,就可以在匯入這些COM介面時將變數定義為dynamic而不是object,省掉了強制類型轉換。

PIA(Primary Interop Assemblies)是根據COM API產生的.Net Assembly,一般體積比較大。在4.0中運行時不需要PIA的存在,編譯器會判斷你的程式具體使用了哪一部分COM API,只把這部分用PIA封裝,直接加入到你自己程式的Assembly裡面。

Co- and Contra-Variance

實在是不知道怎麼翻譯這兩個詞。

(感謝Ariex,徐少俠,AlexChen的提示,應翻譯為協變和逆變,http://msdn.microsoft.com/zh-cn/library/ms173174(VS.80).aspx)

在C#中,下面的類型轉換是非法的:

IList<string> strings = new List<string>();IList<object> objects = strings;

因為你有可能會這樣做,而編譯器的靜態檢查無法查出錯誤:

objects[0] = 5;string s = strings[0];

4.0中在聲明generic的Interface及Delegate時可以加in及out關鍵字,如:

public interface IEnumerable<out T> : IEnumerable{IEnumerator<T> GetEnumerator();}public interface IEnumerator<out T> : IEnumerator{bool MoveNext();T Current { get; }}
public interface IComparer<in T>{public int Compare(T left, T right);}

out關鍵字的意思是說IEnumerable<T>中T只會被用在輸出中,值不會被改變。這樣將IEnumerable<string>轉為IEnumerable<object>類型就是安全的。

in的意思正好相反,是說IComparer<T>中的T只會被用在輸入中,這樣就可以將IComparer<object>安全的轉為IComparer<string>類型。

前者被稱為Co-Variance, 後者就是Contra-Variance。

.Net4.0中使用out/in聲明的Interface:

System.Collections.Generic.IEnumerable<out T>System.Collections.Generic.IEnumerator<out T>System.Linq.IQueryable<out T>System.Collections.Generic.IComparer<in T>System.Collections.Generic.IEqualityComparer<in T>System.IComparable<in T>

Delegate:

System.Func<in T, …, out R>System.Action<in T, …>System.Predicate<in T>System.Comparison<in T>System.EventHandler<in T>
Compiler as a Service

4.0中增加了與編譯器相關的API,這樣就可以將字串作為代碼動態編譯執行,跟javascript好像。

Video的最後,Anders做了一個很酷的demo,大概只用了二三十行代碼,就實現了在控制台中直接執行C#語句,定義並調用函數,動態建立windows form,添加button等功能,看起來完全不遜色於Python,Ruby之類語言的控制台。

 

沉寂了n年之後,CLR終於要出新版本了,這回Jeffrey Richter大俠沒有借口不出新版的CLR via C#了吧:)

 

Reference:

  1. 視頻: http://channel9.msdn.com/pdc2008/TL16/
  2. PPT:http://mschnlnine.vo.llnwd.net/d1/pdc08/PPTX/TL16.pptx
  3. 範例程式碼及文檔(New features in C# 4.0):http://code.msdn.microsoft.com/csharpfuture
相關文章

聯繫我們

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