全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:940
推到 Plurk!
推到 Facebook!

Visual C# .NET 2003 語言的改變

 
axsoft
版主


發表:681
回覆:1056
積分:969
註冊:2002-03-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-05-29 17:08:11 IP:61.218.xxx.xxx 未訂閱

Visual C# .NET 2003 語言的改變

Prashant Sridharan Microsoft Corporation 適用於: Microsoft Visual Studio® C# 2003 摘要:為了與歐洲電腦製造商協會 (ECMA) 的 C# 規範完全相容,Microsoft Corporation 對 C# 編譯器的實現進行了幾處改動。這些改動將在多方面影響現有的程式碼,因此用戶必須檢查他們的程式碼以確保這些程式碼符合 C# 編程語言必需的和推薦的使用要求。 目錄 背景 C# 語言的新功能 實現的改變 小結 背景 2001 年年底,ECMA 將 C# 編程語言批准為一項標準 (ECMA-334)。為了與 Microsoft 在 C# 和公共語言接頭 (CLI) 標準化工作方面的舉措保持一致,Microsoft 遵循 ECMA C# 標準的精神和文字規範對 C# 編譯器進行了幾處小的改動。另外,Microsoft 在遵循 C# 標準規範的同時對 C# 實現作了一些額外的小改動,並更正了 C# 程序員遇到的一些編譯器問題和錯誤。其中的每處改動都可能導致使用 Visual C# .NET 2002 版編譯器編寫的程式碼在用於 Visual C# .NET 2003 之前必須進行修改。 C# 語言的新功能 Visual C# .NET 2003 版的 C# 語言中增加了兩個新功能。第一,編譯器現在支持 #line hidden 預處理器指令。#line hidden 指令主要用於來源碼產生器,它通知編譯器忽略緊跟在 #line hidden 指令後面的所有程式碼行的偵錯程序信息,直到遇到下一個 #line 指令為止(該 #line 指令的偵錯程序信息也一併被忽略),這裡假設它們中間不會立即碰到下一個 #line hidden 預處理指令。在下面的示例中,編譯器產生了 IL 程式碼,其中的 WriteLine 語句不包含偵錯信息。這樣,偵錯應用程式的程序員將無法檢視「隱藏」的程式碼並檢查其中的內容: public class Customer { public static void Main() { MyClass c = new MyClass(); c.ExecuteCommand(); #line hidden Console.WriteLine("顯示一些文字"); Console.WriteLine("顯示一些文字"); Console.WriteLine("顯示一些文字"); #line c.ProcessCommand(); c.Close(); } } 然而,#line hidden 指令並不隱藏編譯器錯誤。當然,編譯器仍然將程式碼編譯到 IL 中,且程式碼仍舊執行;編譯器只是禁止偵錯程序進入它的內容。 第二個 C# 新功能涉及 XML 註釋,是根據 ECMA 標準增加的。C# 現在支持在使用「斜線和星號」符號(/* 和 */)編寫的多行註釋中增加 XML 註釋。下面的 XML 註釋在 2003 版的 C# 編譯器中是合法的: /** 這是 註釋 */ 此外,出於完整性的考慮(但實際上絕不推薦),程序員可以混合併匹配註釋樣式,同時仍然能夠編寫出有效的 XML 註釋程式碼。這樣,下面的這個註釋聲明現在也是合法的: /** 這是 註釋 */ /// 實現的改變 2003 版的 C# 編譯器和 2002 版也有微小的區別。在有些情況下,這些區別可能會導致程式碼無法編譯,或導致其執行方式與應執行的方式大相逕庭。 「Foreach」語句的改變 現在,foreach 語句可以動態地檢查它所迭代的資料結構中是否存在 IDisposable 接頭。以前,編譯器從不動態地檢查 Idisposable 接頭是否存在,除非從 GetEnumerator 返回的類型已實現了 IEnumerator 接頭。然而,如果此類型對於實現 Idisposable 是靜態已知的,則編譯器將一直使用 Dispose。換句話說,如果迭代程序類型實現了枚舉器設計模式,但沒有專門實現 IEnumerator 接頭,編譯器就不會使用 Dispose 方法,除非 iterator 類型對於實現 IDisposable 接頭是靜態已知的。 現在,編譯器在檢測是否存在 IDisposable 接頭時,無論迭代程序類型是否實現 IEnumerator,都將使用 Dispose 方法(如果已實現)。在下面的示例中,Visual C# .NET 2002 編譯器未使用 Dispose 方法,但 Visual C# .NET 2003 編譯器使用了該方法: abstract class Base { public int Current { get; } public bool MoveNext(); } class Derived: Base, IDisposable { // Base 和 IDisposable 的實現 } class MyClass { public Base GetEnumerator() { return new Derived(); } } 當 foreach 語句在某個對象集合中使用迭代時,它將執行 GetEnumerator 方法並接收轉換為 Base 類型的 Derived 實例作為它的迭代程序類型。當然,Base 類型無需為了使用它的 Current 和 MoveNext 方法而實現 Ienumerator 接頭。在早期編譯器中,Derived 類型的 Dispose 方法不被使用,因為它不實現 IEnumerator,並且類 Base 對於實現 Idisposable 不是靜態已知的。在新的編譯器中,Dispose 方法被使用,因為編譯器在所有 foreach 語句的迭代程序類型中檢查是否存在 Idisposable 接頭。由於 GetEnumerator 使用的結果是一個轉換為 Base 類型的 Derived 類型,並且由於 Derived 類型實現 Idisposable 接頭,因此編譯器動態檢查 Idisposable 接頭是否存在,會導致對 Dispose 方法的使用。 屬性內容聲明的改變 ECMA C# 標準明確禁止為相應的屬性內容新增獲取和設置函數。實際上,C# 編譯器將屬性內容聲明轉換為獲取和設置函數,以便不支持屬性內容的語言也可以訪問資料。因此,下面的程式碼是無效的,因為編譯器會產生 get_Prop 和 set_Prop 方法,而這兩個方法與用戶聲明的方法發生衝突: public class MyClass { public int Prop { get { } set { } } // 現在屬於非法函數 public int get_Prop() { } // 現在屬於非法函數 public void set_Prop(int val) { } } 以前,C# 編譯器允許新增此類函數,顯然這是一個軟體錯誤。2003 版的 C# 編譯器糾正了這個錯誤。 作為此編譯器錯誤糾正的必然結果,C# 編譯器將不再允許顯式新增產生屬性內容的獲取和設置函數(如果將屬性內容定義為接頭實現的結果)。在下面的示例中,2003 版的 C# 編譯器不再允許在 Derived 類中顯式實現 IMyInterface.get_Prop 和 IMyInterface.set_Prop 方法: interface IMyInterface { public int Prop { get; set; } } public class Derived : IMyInterface { public int Prop { get { } set { } } // 非法 public int IMyInterface.get_Prop() { } // 非法 public void IMyInterface.set_Prop(int val) { } } 其他改變 C# 編譯器的早期版本允許不相容地使用屬性內容。2003 版的 C# 編譯器已經糾正了這些用法,因此更符合 ECMA 規範。首先是對 C# 編譯器進行了糾正,不允許在其參數列表中使用未在屬性內容類聲明中聲明為 public 的命名參數。例如,如果某個 AuthorAttribute 類是使用名為 authorName 的私有字段新增的,則下面的語句在 C# 編譯器的早期版本中是允許的,但在 C# 2003 編譯器中卻會導致錯誤: [Author(authorName="microsoftuser")] public class MyClass { } 第二,ObsoleteAttribute 現在可以套用到運算符,這樣程序員就可以使重載的運算符函數失效。最後,編譯器以前對於無法識別的屬性內容位置常常產生一個錯誤,而現在則根據 ECMA C# 規範的要求只產生一個警告。 另外,C# 編譯器以前接受用戶定義的移位運算符參數(<< 和 >>),而根據 ECMA C# 規範,這些參數是無效的。例如,移位運算符以前可以按以下方式進行聲明,即將封裝類的類型聲明為第二個操作數: public class MyClass { public static MyClass operator <<(int I, MyClass c) { } public static void Main() { } } 按照規範,如果向左移位運算符被重載,則二進制運算符的操作數列表中的第一個參數必須為封裝類型。同樣,如果向右移位運算符被重載,則二進制運算符的操作數列表中的第二個參數必須為封裝類型。下面的程式碼示例演示了向左移位運算符的正確聲明方式: public class MyClass { public static MyClass operator <<( MyClass c, int i) { } public static void Main() { } } 最後,還加入了幾個用於糾正編譯器錯誤的修復,包括: 對顯式賦值算法的糾正,使編譯器對於符合 ECMA C# 規範的程式碼不再報錯。 枚舉類型現在可以轉換為字串(詳見 ECMA C# 規範中的說明)。 內部虛警告已被刪除,因為內部虛函數無法在程序集外被重寫。 小結 C# 編譯器以不同的方式實現了幾個功能,從而獲得了比前一版更高的性能。但這些改進不會影響對程式碼的編譯和執行: 在迭代字串串的元素時,foreach 語句現在使用字串串的索引器而非枚舉器模式,這樣使性能更佳。 現在,C# 編譯器在處理浮點運算和十進制數學運算方面更嚴格地遵循 ECMA C# 規範。 幾個軟體錯誤已被修復,使控制流得到優化。 HAVE A NICE DAY 發表人 - axsoft 於 2003/05/29 17:20:10
系統時間:2024-05-11 3:37:03
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!