1. 程式人生 > 其它 >C# 語言歷史版本特性(C# 1.0到C# 8.0彙總

C# 語言歷史版本特性(C# 1.0到C# 8.0彙總

C# 語言歷史版本特性(C# 1.0到C# 8.0彙總)

歷史版本

C#作為微軟2000年以後.NET平臺開發的當家語言,發展至今具有17年的歷史,語言本身具有豐富的特性,微軟對其更新支援也十分支援。微軟將C#提交給標準組織ECMA,C# 5.0目前是ECMA釋出的最新規範,C# 6.0還是草案階段,C# 7.1是微軟當前提供的最新規範。

這裡僅僅列個提綱,由於C# 5.0是具有ECMA標準規範的版本,所以選擇C# 5.0作為主要版本學習,並專題學習C# 6.0,7.0版本新特性。

C#語言規範GitHub庫參見:https://github.com/dotnet/csharplang

C#語言路線圖及開發中的特性參見:

https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md

語言版本釋出時間.NET Framework要求Visual Studio版本
C# 1.02002.1.NET Framework 1.0Visual Studio .NET 2002
C# 1.1\1.22003.4.NET Framework 1.1Visual Studio .NET 2003
C# 2.02005.11.NET Framework 2.0Visual Studio 2005
C# 3.02007.11.NET Framework 2.0\3.0\3.5Visual Studio 2008
C# 4.02010.4.NET Framework 4.0Visual Studio 2010
C# 5.02012.8.NET Framework 4.5Visual Studio 2012\2013
C# 6.02015.7.NET Framework 4.6Visual Studio 2015
C# 7.02017.3.NET Framework 4.6.2Visual Studio 2017
C# 7.12017.6.NET FrameworkVisual Studio 2017 v15.3預覽版
C# 8.0待發布.NET Framework 4.7.1Visual Studio 2017 v15.7

C# 1.0 特性

第1個版本,程式語言最基礎的特性。

  • Classes:面向物件特性,支援類型別
  • Structs:結構
  • Interfaces:介面
  • Events:事件
  • Properties:屬性,類的成員,提供訪問欄位的靈活方法
  • Delegates:委託,一種引用型別,表示對具有特定引數列表和返回型別的方法的引用
  • Expressions,Statements,Operators:表示式、語句、操作符
  • Attributes:特性,為程式程式碼新增元資料或宣告性資訊,執行時,通過反射可以訪問特性資訊
  • Literals:字面值(或理解為常量值),區別常量,常量是和變數相對的

C# 2特性 (VS 2005)

  • Generics:泛型
  • Partial types:分部型別,可以將類、結構、介面等型別定義拆分到多個檔案中
  • Anonymous methods:匿名方法
  • Iterators:迭代器
  • Nullable types:可以為Null的型別,該類可以是其它值或者null
  • Getter/setter separate accessibility:屬性訪問控制
  • Method group conversions (delegates):方法組轉換,可以將宣告委託代表一組方法,隱式呼叫
  • Co- and Contra-variance for delegates and interfaces:委託、介面的協變和逆變
  • Static classes:靜態類
  • Delegate inference:委託推斷,允許將方法名直接賦給委託變數

C# 3特性 (VS 2008)

  • Implicitly typed local variables:
  • Object and collection initializers:物件和集合初始化器
  • Auto-Implemented properties:自動屬性,自動生成屬性方法,宣告更簡潔
  • Anonymous types:匿名型別
  • Extension methods:擴充套件方法
  • Query expressions:查詢表示式
  • Lambda expression:Lambda表示式
  • Expression trees:表示式樹,以樹形資料結構表示程式碼,是一種新資料型別
  • Partial methods:部分方法

C# 4特性 (VS 2010)

  • Dynamic binding:動態繫結
  • Named and optional arguments:命名引數和可選引數
  • Generic co- and contravariance:泛型的協變和逆變
  • Embedded interop types (“NoPIA”):開啟嵌入型別資訊,增加引用COM元件程式的中立性

C# 5特性 (VS 2012)

  • Asynchronous methods:非同步方法
  • Caller info attributes:呼叫方資訊特性,呼叫時訪問呼叫者的資訊

C# 6特徵 (VS 2015)

  • Compiler-as-a-service (Roslyn)
  • Import of static type members into namespace:支援僅匯入類中的靜態成員
  • Exception filters:異常過濾器
  • Await in catch/finally blocks:支援在catch/finally語句塊使用await語句
  • Auto property initializers:自動屬性初始化
  • Default values for getter-only properties:設定只讀屬性的預設值
  • Expression-bodied members:支援以表示式為主體的成員方法和只讀屬性
  • Null propagator (null-conditional operator, succinct null checking):Null條件操作符
  • String interpolation:字串插值,產生特定格式字串的新方法
  • nameof operator:nameof操作符,返回方法、屬性、變數的名稱
  • Dictionary initializer:字典初始化

C# 7 特徵 (Visual Studio 2017)

  • Out variables:out變數直接宣告,例如可以out in parameter
  • Pattern matching:模式匹配,根據物件型別或者其它屬性實現方法派發
  • Tuples:元組
  • Deconstruction:元組解析
  • Discards:沒有命名的變數,只是佔位,後面程式碼不需要使用其值
  • Local Functions:區域性函式
  • Binary Literals:二進位制字面量
  • Digit Separators:數字分隔符
  • Ref returns and locals:引用返回值和區域性變數
  • Generalized async return types:async中使用泛型返回型別
  • More expression-bodied members:允許構造器、解析器、屬性可以使用表示式作為body
  • Throw expressions:Throw可以在表示式中使用

C# 7.1 特徵 (Visual Studio 2017 version 15.3)

  • Async main:在main方法用async方式
  • Default expressions:引入新的字面值default
  • Reference assemblies:
  • Inferred tuple element names:
  • Pattern-matching with generics:

C# 8.0 特徵 (Visual Studio 2017 version 15.7)

  • Default Interface Methods 預設介面實現
  • Nullable reference type NullableReferenceTypes 非空和可控的資料型別
  • Recursive patterns 遞迴模式
  • Async streams 非同步資料流
  • Caller expression attribute 呼叫方法表示式屬性
  • Target-typed new
  • Generic attributes 通用屬性
  • Ranges
  • Default in deconstruction
  • Relax ordering of ref and partial modifiers

標籤:C#新特性,C#8.0,C#版本與net framework版本對照,C#歷史版本

C#5.0版本

像C#4.0版本一樣,C#5.0版本中沒有太多功能 - 但是其中一個功能非常龐大。

  • 非同步/等待
  • CallerInfoAttributes

當C#5.0釋出時,它實際上改變了C#開發人員編寫非同步程式碼的方式。雖然直到今天仍然有很多困惑,但我在這裡向您保證,這比大多數人想象的要簡單得多。這是C#的一個重大飛躍 - 它引入了一個語言級別的非同步模型,它極大地賦予了開發人員編寫外觀和感覺同步(或者至少是連續的)的“非同步”程式碼。

非同步程式設計在處理I/O繫結工作負載(如與資料庫,網路,檔案系統等進行互動)時非常強大。非同步程式設計通過使用非阻塞方法幫助處理吞吐量。這種方法使用了一個透明的非同步狀態機中的掛點和相應的延續。

同樣,如果CPU負載計算的工作量很大,則可能需要考慮非同步執行此項工作。這將有助於使用者體驗,因為UI執行緒不會被阻塞,而是可以自由地響應其他UI互動。

編者注:這裡有一些關於C#非同步程式設計的最佳實踐,使用Async Await.

在C#5.0中,當語言添加了兩個新的關鍵字async和await時,非同步程式設計被簡化了。這些關鍵字適用於Task。下表將作為參考:

async-await

Task表示非同步操作。操作可以通過Task返回值,也可以通過Task返回void。當您使用async關鍵字修飾Task返回方法時,它使方法主體可以使用await關鍵字。當您請求await關鍵字的返回值時,控制流將返回給呼叫者,並且在方法的那個點執行暫停。當await的操作完成後,在同一點上恢復執行。部分程式碼如下!


   
  1. class IOBoundAsyncExample
  2. {
  3. private const string Url = "http://api.icndb.com/jokes/random?limitTo=[nerdy]";
  4. internal async Task GetJokeAsync()
  5. {
  6. using ( var client = new HttpClient())
  7. {
  8. var response = await client.GetStringAsync(Url);
  9. var result = JsonConvert.DeserializeObject(response);
  10. return result.Value.Joke;
  11. }
  12. }
  13. }
  14. public class Result
  15. {
  16. [ JsonProperty("type")] public string Type { get; set; }
  17. [ JsonProperty("value")] public Value Value { get; set; }
  18. }
  19. public class Value
  20. {
  21. [ JsonProperty("id")] public int Id { get; set; }
  22. [ JsonProperty("joke")] public string Joke { get; set; }
  23. }

我們用一個名為GetJokeAsync的方法定義一個簡單的類。該方法是返回Task,這意味著我們的GetJokeAsync方法最終會給您一個字串,或者可能出錯。

該方法使用async關鍵字進行修飾,該關鍵字允許使用等待關鍵字。我們例項化並使用一個HttpClient物件。然後我們呼叫GetStringAsync函式,它接受一個字串url並返回一個Task 。我們等待從GetStringAsync呼叫返回的Task。

當響應已經準備好時,就會繼續發生並控制從我們曾經掛起的位置恢復。然後,我們將JSON反序列化到Result類的例項中,並返回Joke屬性。

一些我最喜歡的成果

  • 查克·諾里斯(Chuck Norris)可以用單一的斷言來測試整個應用程式。
  • 查克·諾里斯(Chuck Norris)可以編譯語法錯誤。
  • 專案經理永遠不會要求查克·諾里斯(Chuck Norris)做出估計。

歡鬧隨之而來!我們瞭解了C#5.0的驚人的非同步程式設計模型。

C#6.0版本

C#6.0的推出有很多很大的進步,很難選擇我最喜歡的功能。

  • 字典初始化
  • 異常過濾器
  • 在屬性裡使用Lambda表示式
  • nameof表示式
  • 空值運算子
  • 自動屬性初始化
  • 靜態匯入
  • 字串嵌入值

我把範圍縮小到三個突出特點:空值運算子,字串嵌入值和nameof表示式。

雖然nameof表示式很棒,我幾乎每次都用它來編寫程式碼,但其他兩個特性更有影響力。這讓我在字串嵌入值和空值運算子之間做出決定,這是相當困難的。我決定我最喜歡的是字串嵌入值,這就是為什麼。

空值運算子是偉大的,它允許我寫較少的詳細程式碼,但它不一定能防止我的程式碼中的錯誤。但是,使用字串嵌入值可以防止執行時錯誤 - 這是我的書中的一個勝利。

使用$符號啟動字串文字時,將啟用C#中的字串嵌入值語法。這指示C#編譯器打算用各種C#變數,邏輯或表示式來插入此字串。這是手動字串連線甚至是string.Format方法的一個主要升級。考慮以下:


   
  1. class Person
  2. {
  3. public string FirstName { get; set; }
  4. public string LastName { get; set; }
  5. public override string ToString()
  6. => string.Format( "{0} {1}", FirstName);
  7. }

我們有一個簡單的Person類,具有兩個名稱屬性,用於名字和姓氏。我們重寫ToString方法並使用string.Format。問題是,編譯時,由於開發人員顯然希望將姓氏也作為結果字串的一部分,因此很容易出錯,這一點在“{0} {1} ”引數中很明顯。同樣,開發人員可以很容易地交換名稱或正確提供兩個名稱引數,但混亂的格式文字只包括第一個索引,等等...現在我們可以考慮使用字串嵌入值。


   
  1. class Person
  2. {
  3. public string FirstName { get; set; } = "David";
  4. public string LastName { get; set; } = "Pine";
  5. public DateTime DateOfBirth { get; set; } = new DateTime( 1984, 7, 7);
  6. public override string ToString()
  7. => $"{FirstName} {LastName} (Born {DateOfBirth:MMMM dd, yyyy})";
  8. }

我冒昧新增DateOfBirth屬性和一些預設的屬性值。另外,我們現在在我們的ToString方法的覆蓋中使用字串嵌入值。作為一名開發人員,犯上述錯誤要困難得多。最後,我也可以在插值表示式中進行格式化。注意第三次嵌入值,DateOfBirth是一個DateTime - 因此我們可以使用您已經習慣的所有標準格式。只需使用:運算子來分隔變數和格式。

示例輸出

· David Pine (Born July 7, 1984)

編輯注:有關C#6.0新特性的詳細內容,請閱讀www.dotnetcurry.com/csharp/1042/csharp-6-new-features

C#7.0版本

從所有整合到 C# 7.0的特性中。

  • 更多的函式成員的表示式體
  • 區域性函式
  • Out變數
  • 模式匹配
  • 區域性變數和引用返回
  • 元組和解構

我結束了模式匹配,元組和Out變數之間的爭論。我最終選擇了Out變數,這是為什麼。

模式匹配但是我真的不經常使用它,至少現在還沒有。也許以後我會更多地使用它,但是對於我迄今為止編寫的所有c#程式碼,沒有太多地方可以利用它。同樣,這是一個很棒的功能,我確實看到了它的位置 - 只是在C#7.0中這不是我最喜歡的。

元組也是一個很好的補充。元組是語言的重要組成部分,成為一流的公民是非常棒的。我會說,“寫tem1,.Item2,.Item3等...的日子已經過去了,但這並不一定是正確的。反序列化失去了元組的名稱,使得這個公共API不那麼有價值

我也不喜歡ValueTuple型別是可變的這一事實。我只是不明白設計者的決定。我希望有人能給我解釋一下,但感覺有點像疏忽。因此,我得到了選擇out變數的特性。

自從C#版本1.0以來,try-parse模式已經在各種值型別中出現了。模式如下:


   
  1. public boolean TryParse(string value, out DateTime date)
  2. {
  3. // 為了簡便起見,我們省略了.....
  4. }

該函式返回一個布林值,指示給定的字串值是否能夠被解析。如果為true,則將分析的值分配給生成的輸出引數date。它的使用如下:


   
  1. DateTime date;
  2. if (DateTime.TryParse(someDateString, out date))
  3. {
  4. // date現在是解析值
  5. }
  6. else
  7. {
  8. // date是DateTime.MinValue,預設值
  9. }

這種模式是有用的,但有點麻煩。有時,不管解析是否成功,開發人員都會採取相同的操作過程。有時使用預設值是可以的。C#7.0中的out變數使得這個更復雜,不過在我看來不那麼複雜。

示例如下:


   
  1. if (DateTime.TryParse(someDateString, out var date))
  2. {
  3. // date現在是解析值
  4. }
  5. else
  6. {
  7. // date是DateTime.MinValue,預設值
  8. }

現在我們移除了if語句塊的外部宣告,並把宣告作為引數本身的一部分。使用var是合法的,因為型別是已知的。最後,date變數的範圍沒有改變。它從內聯宣告洩漏到if塊的頂部。

你可能會問自己:“為什麼這是他最喜歡的功能之一?”.....這種感覺真的沒有什麼變化。

但是這改變了一切!

它使我們的C#更具有表現力。每個人都喜歡擴充套件方法,對 - 請考慮以下幾點:


   
  1. public static class StringExtensions
  2. {
  3. private delegate bool TryParseDelegate(string s, out T result);
  4. private static T To(string value, TryParseDelegate parse)
  5. => parse( value, out T result) ? result : default;
  6. public static int ToInt32(this string value)
  7. => To( value, int.TryParse);
  8. public static DateTime ToDateTime(this string value)
  9. => To( value, DateTime.TryParse);
  10. public static IPAddress ToIPAddress(this string value)
  11. => To( value, IPAddress.TryParse);
  12. public static TimeSpan ToTimeSpan(this string value)
  13. => To( value, TimeSpan.TryParse);
  14. }

這個擴充套件方法類很簡潔,表達能力強。在定義了遵循try-parse模式的私有委託之後,我們可以編寫一個泛型複合函式,它需要一個泛型型別的引數、要解析的字串值和TryParseDelegate。現在我們可以安全地依賴這些擴充套件方法,考慮以下幾點::


   
  1. public class Program
  2. {
  3. public static void Main( string[] args)
  4. {
  5. var str =
  6. string.Join(
  7. "",
  8. new[] { "James", "Bond", " +7 " }.Select(s => s.ToInt32()));
  9. Console.WriteLine(str); // 列印 "007"
  10. }
  11. }

編輯注:要了解C#7的所有新功能,請檢視本教程www.dotnetcurry.com/csharp/1286/csharp-7-new-expected-features

結論

這篇文章對我個人而言頗具挑戰性。我喜歡C#的許多特性,因此每次釋出只收集一個最喜歡的內容是非常困難的。

每個較新版本的C#都包含了強大而有影響力的功能。C#語言團隊以無數的方式進行創新 - 其中之一就是引入點發布。在撰寫本文時,C# 7.1和 7.2已正式發貨。作為C#開發人員,我們生活在一個激動人心的語言時代!

然而,對我來說,對所有這些特性進行分類是相當有見地的;因為它幫助我們瞭解了什麼是實際的,最影響我的日常發展。一如既往,努力成為一個務實的開發者!並不是語言中所有可用的特性都是當前任務所必需的,但瞭解什麼是可用的,這一點很重要。

當我們期待C#8的建議和原型時,我對C#的未來感到興奮。它看起來確實很有希望,而且語言正在積極地試圖緩解“價值億萬美金的錯誤”。

歡迎轉載,轉載請註明翻譯原文出處(本文章),原文出處(原部落格地址),然後謝謝觀看

如果覺得我的翻譯對您有幫助,請點選推薦支援:)

C# 6.0+VS2015:win8/win10;空值運算子,字串嵌入值和nameof表示式。

C# 7.0+VS2018:win10元組和解構.

vs2018(c#8.0):正在開發中。