日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

C#知多少 | 每个版本都更新了什么?

發布時間:2023/12/4 C# 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C#知多少 | 每个版本都更新了什么? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

總所周知,.NET5.0馬上就要來了,最后一個預覽版RC2也已經發布了,在11月的時候,我們就正式的發布了,然后我們就可以遷移使用了,當然今天說的重點不是.NET,今天說的是伴隨著.NET5一起到來的C#9.0,既然要了解9.0,肯定要對之前的版本也稍微了解一下,至少不會面試的時候出現:XXX這個功能用過么,哪個版本出來的知道么?一問三不知的尷尬情景。雖然官網都有,但是我相信有一小部分不看,所以還是發出來吧。

咱們就采用從小到大的順序講解吧,從6.0開始,5.0就太老了,基本不會問了,注意是C#,不是MVC,查看的都是官網的,想看更多,點擊【閱讀原文】。


C#6中新增的功能

1get 只讀屬性

簡潔的語法來創建不可變類型,僅有get訪問器:

public string FirstName { get; } public string LastName { get; }

當然很多時候,我們使用的是私有化來設置set。

然后通過構造函數來賦值:

public Student(string firstName, string lastName) {if (IsNullOrWhiteSpace(lastName))throw new ArgumentException(message: "Cannot be blank", paramName: nameof(lastName));FirstName = firstName;LastName = lastName; }

2get 屬性初始化表達式

在屬性聲明中聲明自動屬性的初始值,

public ICollection<double> Grades { get; } =?new?List<double>();

聲明處就可以直接被初始化。

3Expression-bodied 函數成員

這適用于方法和只讀屬性。 例如,重寫 ToString() 通常是理想之選:

public override string ToString() => $"{LastName}, {FirstName}";

也可以將此語法用于只讀屬性:

public string FullName => $"{FirstName} {LastName}";

4using 靜態命名空間

using static ?增強功能可用于導入單個類的靜態方法。 指定要使用的類:

using static System.Math;

在 LINQ 查詢中會經常看到這種情況。 可以通過導入 Enumerable 或 Queryable 來導入 LINQ 模式。

5Null 條件運算符

Null 條件運算符使 null 檢查更輕松、更流暢 ?。 將成員訪問 . 替換為 ?.:

var first = person?.FirstName;

如果person為空,返回的值就是null,是string的默認值,如果FirstName是int類型,那返回的就是int的默認值0。

6$ 字符串內插

新的字符串內插功能可以在字符串中嵌入表達式。 使用 $ 作為字符串的開頭,并使用 { 和 } 之間的表達式代替序號:

public string GetGradePointPercentage() =>$"Name: {LastName}, {FirstName}. G.P.A: {Grades.Average():F2}";

上一行代碼將 Grades.Average() 的值格式設置為具有兩位小數的浮點數。

7when?異常篩選器

“異常篩選器”是確定何時應該應用給定的catch子句的子句 。如果用于異常篩選器的表達式計算結果為true,則catch子句將對異常執行正常處理。 如果表達式計算結果為false,則將跳過catch子句。一種用途是檢查有關異常的信息,以確定catch子句是否可以處理該異常:

public static async Task<string> MakeRequest() {WebRequestHandler webRequestHandler = new WebRequestHandler();webRequestHandler.AllowAutoRedirect = false;using (HttpClient client = new HttpClient(webRequestHandler)){var stringTask = client.GetStringAsync("https://docs.microsoft.com/en-us/dotnet/about/");try{var responseText = await stringTask;return responseText;}catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301")){return "Site Moved";}} }

8nameof 表達式

nameof 表達式的計算結果為符號的名稱。 每當需要變量、屬性或成員字段的名稱時,這是讓工具正常運行的好辦法,說白了就是更好的重構:

if (IsNullOrWhiteSpace(lastName))throw new ArgumentException(message: "Cannot be blank", paramName: nameof(lastName));

9Catch 和 Finally 塊中的 Await

現在可以在 catch 或 finally 表達式中使用 await。 這通常用于日志記錄方案:

public static async Task<string> MakeRequestAndLogFailures() {await logMethodEntrance();var client = new System.Net.Http.HttpClient();var streamTask = client.GetStringAsync("https://localHost:10000");try {var responseText = await streamTask;return responseText;} catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301")){await logError("Recovered from redirect", e);return "Site Moved";}finally{await logMethodExit();client.Dispose();} }

10索引器初始化關聯集合

可以將集合初始值設定項與 Dictionary<TKey,TValue> 集合和其他類型一起使用,在這種情況下,可訪問的 Add 方法接受多個參數。 新語法支持使用索引分配到集合中:

private Dictionary<int, string> webErrors = new Dictionary<int, string> {[404] = "Page not Found",[302] = "Page moved, but left a forwarding address.",[500] = "The web server can't come out to play today." };

C#7.x 中新增的功能

1out 變量

可以在方法調用的參數列表中聲明 out 變量,而不是編寫單獨的聲明語句::

if (int.TryParse(input, out int result))Console.WriteLine(result); elseConsole.WriteLine("Could not parse input");

為清晰明了,可能需指定 out 變量的類型,如上所示。 但是,該語言支持使用隱式類型的局部變量:

if (int.TryParse(input, out var answer))Console.WriteLine(answer); elseConsole.WriteLine("Could not parse input");

2Tuple 元組

低于 C# 7.0 的版本中也提供元組,但它們效率低下且不具有語言支持。這意味著元組元素只能作為 Item1 和 Item2 等引用。

可以通過為每個成員賦值來創建元組,并可選擇為元組的每個成員提供語義名稱:

(string Alpha, string Beta) namedLetters = ("a", "b"); Console.WriteLine($"{namedLetters.Alpha}, {namedLetters.Beta}");

在進行元組賦值時,還可以指定賦值右側的字段的名稱:

var alphabetStart = (Alpha: "a", Beta: "b"); Console.WriteLine($"{alphabetStart.Alpha}, {alphabetStart.Beta}");

使用的時候,可以直接點出來:

alphabetStart.Alpha alphabetStart.Beta

3_ 棄元

C# 增添了對棄元的支持。 棄元是一個名為 _(下劃線字符)的只寫變量,可向單個變量賦予要放棄的所有值。 棄元類似于未賦值的變量;不可在代碼中使用棄元(賦值語句除外):

public class Example {public static void Main(){var (_, _, _, pop1, _, pop2) = QueryCityDataForYears("New York City", 1960, 2010);Console.WriteLine($"Population change, 1960 to 2010: {pop2 - pop1:N0}");}private static (string, double, int, int, int, int) QueryCityDataForYears(string name, int year1, int year2){int population1 = 0, population2 = 0;double area = 0;if (name == "New York City"){area = 468.48;if (year1 == 1960){population1 = 7781984;}if (year2 == 2010){population2 = 8175133;}return (name, area, year1, population1, year2, population2);}return ("", 0, 0, 0, 0, 0);} }

4is 模式匹配

模式匹配支持 is 表達式和 switch 表達式。 每個表達式都允許檢查對象及其屬性以確定該對象是否滿足所尋求的模式。 使用 when 關鍵字來指定模式的其他規則:

public static int SumPositiveNumbers(IEnumerable<object> sequence) {int sum = 0;foreach (var i in sequence){switch (i){case 0:break;case IEnumerable<int> childSequence:{foreach(var item in childSequence)sum += (item > 0) ? item : 0;break;}case int n when n > 0:sum += n;break;case null:throw new NullReferenceException("Null found in sequence");default:throw new InvalidOperationException("Unrecognized type");}}return sum; }
  • case 0: 是常見的常量模式。

  • case IEnumerable<int> childSequence: 是一種類型模式。

  • case int n when n > 0: 是具有附加 when 條件的類型模式。

  • case null: 是 null 模式。

  • default: 是常見的默認事例。

5本地函數(內部)

本地函數使你能夠在另一個方法的上下文內聲明方法。 本地函數使得類的閱讀者更容易看到本地方法僅從聲明它的上下文中調用。

public static IEnumerable<char> AlphabetSubset3(char start, char end) {if (start < 'a' || start > 'z')throw new ArgumentOutOfRangeException(paramName: nameof(start), message: "start must be a letter");if (end < 'a' || end > 'z')throw new ArgumentOutOfRangeException(paramName: nameof(end), message: "end must be a letter");if (end <= start)throw new ArgumentException($"{nameof(end)} must be greater than {nameof(start)}");return alphabetSubsetImplementation();IEnumerable<char> alphabetSubsetImplementation(){for (var c = start; c < end; c++)yield return c;} }

注意上邊的alphabetSubsetImplementation方法,是在內部定義的。

同樣可以使用異步:

public Task<string> PerformLongRunningWork(string address, int index, string name) {if (string.IsNullOrWhiteSpace(address))throw new ArgumentException(message: "An address is required", paramName: nameof(address));if (index < 0)throw new ArgumentOutOfRangeException(paramName: nameof(index), message: "The index must be non-negative");if (string.IsNullOrWhiteSpace(name))throw new ArgumentException(message: "You must supply a name", paramName: nameof(name));return longRunningWorkImplementation();async Task<string> longRunningWorkImplementation(){var interimResult = await FirstWork(address);var secondResult = await SecondStep(index, name);return $"The results are {interimResult} and {secondResult}. Enjoy.";} }

當然也支持某些使用lambda表達式來完成。

6數字文本語法改進

C# 7.0 包括兩項新功能,可用于以最可讀的方式寫入數字來用于預期用途:二進制文本和數字分隔符 。在創建位掩碼時,或每當數字的二進制表示形式使代碼最具可讀性時,以二進制形式寫入該數字:

public const int Sixteen = 0b0001_0000; public const int ThirtyTwo = 0b0010_0000; public const int SixtyFour = 0b0100_0000; public const int OneHundredTwentyEight = 0b1000_0000;

常量開頭的 0b 表示該數字以二進制數形式寫入。 二進制數可能會很長,因此通過引入 _ 作為數字分隔符通常更易于查看位模式,如上面二進制常量所示。 數字分隔符可以出現在常量的任何位置。 對于十進制數字,通常將其用作千位分隔符:

public const long BillionsAndBillions = 100_000_000_000;

C#8.0中新增的功能

“.NET Core 3.x”和“.NET Standard 2.1”支持 C# 8.0;

1Readonly 成員

可將 readonly 修飾符應用于結構的成員。 它指示該成員不會修改狀態。 這比將 readonly 修飾符應用于 struct 聲明更精細。 ?請考慮以下可變結構:

public readonly double Distance => Math.Sqrt(X * X + Y * Y);

2默認接口方法

現在可以將成員添加到接口,并為這些成員提供實現。 借助此語言功能,API 作者可以將方法添加到以后版本的接口中,而不會破壞與該接口當前實現的源或二進制文件兼容性。 現有的實現繼承默認實現。

public interface ICustomer {IEnumerable<IOrder> PreviousOrders { get; }DateTime DateJoined { get; }DateTime? LastOrder { get; }string Name { get; }IDictionary<DateTime, string> Reminders { get; } }

?

3Switch 表達式升級

通常情況下,switch 語句在其每個 case 塊中生成一個值。借助 Switch 表達式,可以使用更簡潔的表達式語法。

public static RGBColor FromRainbowClassic(Rainbow colorBand) {switch (colorBand){case Rainbow.Red:return new RGBColor(0xFF, 0x00, 0x00);case Rainbow.Orange:return new RGBColor(0xFF, 0x7F, 0x00);case Rainbow.Yellow:return new RGBColor(0xFF, 0xFF, 0x00);case Rainbow.Green:return new RGBColor(0x00, 0xFF, 0x00);case Rainbow.Blue:return new RGBColor(0x00, 0x00, 0xFF);case Rainbow.Indigo:return new RGBColor(0x4B, 0x00, 0x82);case Rainbow.Violet:return new RGBColor(0x94, 0x00, 0xD3);default:throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand));}; }

這里有幾個語法改進:

  • 變量位于 switch 關鍵字之前。 不同的順序使得在視覺上可以很輕松地區分 switch 表達式和 switch 語句。

  • 將 case 和 : 元素替換為 =>。 它更簡潔,更直觀。

  • 將 default 事例替換為 _ 棄元。

  • 正文是表達式,不是語句。

public static RGBColor FromRainbow(Rainbow colorBand) =>colorBand switch{Rainbow.Red => new RGBColor(0xFF, 0x00, 0x00),Rainbow.Orange => new RGBColor(0xFF, 0x7F, 0x00),Rainbow.Yellow => new RGBColor(0xFF, 0xFF, 0x00),Rainbow.Green => new RGBColor(0x00, 0xFF, 0x00),Rainbow.Blue => new RGBColor(0x00, 0x00, 0xFF),Rainbow.Indigo => new RGBColor(0x4B, 0x00, 0x82),Rainbow.Violet => new RGBColor(0x94, 0x00, 0xD3),_ => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)),};

4屬性模式

借助屬性模式,可以匹配所檢查的對象的屬性。 請看一個電子商務網站的示例,該網站必須根據買家地址計算銷售稅。 這種計算不是 Address 類的核心職責。 它會隨時間變化,可能比地址格式的更改更頻繁。 銷售稅的金額取決于地址的 State 屬性。 下面的方法使用屬性模式從地址和價格計算銷售稅:

public static decimal ComputeSalesTax(Address location, decimal salePrice) =>location switch{{ State: "WA" } => salePrice * 0.06M,{ State: "MN" } => salePrice * 0.075M,{ State: "MI" } => salePrice * 0.05M,// other cases removed for brevity..._ => 0M};

在 LINQ 查詢中會經常看到這種情況。 可以通過導入 Enumerable 或 Queryable 來導入 LINQ 模式。

5元組模式

一些算法依賴于多個輸入。 使用元組模式,可根據表示為元組的多個值進行切換。 ?以下代碼顯示了游戲“rock, paper, scissors(石頭剪刀布)”的切換表達式::

public static string RockPaperScissors(string first, string second)=> (first, second) switch{("rock", "paper") => "rock is covered by paper. Paper wins.",("rock", "scissors") => "rock breaks scissors. Rock wins.",("paper", "rock") => "paper covers rock. Paper wins.",("paper", "scissors") => "paper is cut by scissors. Scissors wins.",("scissors", "rock") => "scissors is broken by rock. Rock wins.",("scissors", "paper") => "scissors cuts paper. Scissors wins.",(_, _) => "tie"};

如果person為空,返回的值就是null,是string的默認值,如果FirstName是int類型,那返回的就是int的默認值0。

6using 聲明

using 聲明是前面帶 using 關鍵字的變量聲明。 它指示編譯器聲明的變量應在封閉范圍的末尾進行處理。 以下面編寫文本文件的代碼為例:

static int WriteLinesToFile(IEnumerable<string> lines) {using var file = new System.IO.StreamWriter("WriteLines2.txt");// Notice how we declare skippedLines after the using statement.int skippedLines = 0;foreach (string line in lines){if (!line.Contains("Second")){file.WriteLine(line);}else{skippedLines++;}}// Notice how skippedLines is in scope here.return skippedLines;// file is disposed here }

前面的代碼相當于下面使用經典 using 語句的代碼:

static int WriteLinesToFile(IEnumerable<string> lines) {// We must declare the variable outside of the using block// so that it is in scope to be returned.int skippedLines = 0;using (var file = new System.IO.StreamWriter("WriteLines2.txt")){foreach (string line in lines){if (!line.Contains("Second")){file.WriteLine(line);}else{skippedLines++;}}return skippedLines;} // file is disposed here }

7Static 靜態本地函數

現在可以向本地函數添加 static 修飾符,以確保本地函數不會從封閉范圍捕獲(引用)任何變量。

int M() { int y = 5;int x = 7;return Add(x, y);static int Add(int left, int right) => left + right; }

8async 異步流

從 C# 8.0 開始,可以創建并以異步方式使用流。返回異步流的方法有三個屬性:

  • 它是用 async 修飾符聲明的。

  • 它將返回 IAsyncEnumerable<T>。

  • 該方法包含用于在異步流中返回連續元素的 yield return 語句。

  • public static async System.Collections.Generic.IAsyncEnumerable<int> GenerateSequence() {for (int i = 0; i < 20; i++){await Task.Delay(100);yield return i;} }await foreach (var number in GenerateSequence()) {Console.WriteLine(number); }

    異步可釋放:

    從 C# 8.0 開始,語言支持實現 System.IAsyncDisposable 接口的異步可釋放類型。可使用 await using 語句來處理異步可釋放對象。

    9索引和范圍

    范圍指定范圍的開始和末尾 。 包括此范圍的開始,但不包括此范圍的末尾,這表示此范圍包含開始但不包含末尾 。 范圍 [0..^0] 表示整個范圍,就像 [0..sequence.Length] 表示整個范圍。

    請看以下幾個示例。 請考慮以下數組,用其順數索引和倒數索引進行注釋:

    var words = new string[] {// index from start index from end"The", // 0 ^9"quick", // 1 ^8"brown", // 2 ^7"fox", // 3 ^6"jumped", // 4 ^5"over", // 5 ^4"the", // 6 ^3"lazy", // 7 ^2"dog" // 8 ^1 }; // 9 (or words.Length) ^0// 可以使用 ^1 索引檢索最后一個詞: Console.WriteLine($"The last word is {words[^1]}"); // writes "dog"

    以下代碼創建了一個包含單詞“quick”、“brown”和“fox”的子范圍。 它包括 words[1] 到 words[3]。 元素 words[4] 不在該范圍內。

    var quickBrownFox = words[1..4];var allWords = words[..]; // contains "The" through "dog". var firstPhrase = words[..4]; // contains "The" through "fox" var lastPhrase = words[6..]; // contains "the", "lazy" and "dog"

    10null 合并賦值

    C# 8.0 引入了 null 合并賦值運算符 ??=。 僅當左操作數計算為 null 時,才能使用運算符 ??= 將其右操作數的值分配給左操作數。

    List<int> numbers = null; int? i = null;numbers ??= new List<int>(); numbers.Add(i ??= 17); numbers.Add(i ??= 20);Console.WriteLine(string.Join(" ", numbers)); // output: 17 17 Console.WriteLine(i); // output: 17

    C#9.0 中新增的功能

    .NET5支持C#9.0.

    1記錄類型

    C# 9.0 引入了記錄類型,這是一種引用類型,它提供合成方法來提供值語義,從而實現相等性。 默認情況下,記錄是不可變的。

    public record Person {public string LastName { get; }public string FirstName { get; }public Person(string first, string last) => (FirstName, LastName) = (first, last); }

    2Init 僅限的資源庫

    從 C# 9.0 開始,可為屬性和索引器創建 init 訪問器,而不是 set 訪問器。 調用方可使用屬性初始化表達式語法在創建表達式中設置這些值,但構造完成后,這些屬性將變為只讀。 僅限 init 的資源庫提供了一個窗口用來更改狀態。

    public struct WeatherObservation {public DateTime RecordedAt { get; init; }public decimal TemperatureInCelsius { get; init; }public decimal PressureInMillibars { get; init; }public override string ToString() =>$"At {RecordedAt:h:mm tt} on {RecordedAt:M/d/yyyy}: " +$"Temp = {TemperatureInCelsius}, with {PressureInMillibars} pressure"; }

    調用方可使用屬性初始化表達式語法來設置值,同時仍保留不變性:

    var now = new WeatherObservation { RecordedAt = DateTime.Now, TemperatureInCelsius = 20, PressureInMillibars = 998.0m };

    3頂級語句

    頂級語句從許多應用程序中刪除了不必要的流程。只有一行代碼執行所有操作。 借助頂級語句,可使用 using 語句和執行操作的一行替換所有樣本:

    using System;Console.WriteLine("Hello World!");

    如果需要單行程序,可刪除 using 指令,并使用完全限定的類型名稱:

    System.Console.WriteLine("Hello World!");

    4模式匹配增強功能

    C# 9 包括新的模式匹配改進:

    • 類型模式要求在變量是一種類型時匹配

    • 帶圓括號的模式強制或強調模式組合的優先級

    • 聯合 and 模式要求兩個模式都匹配

    • 析取 or 模式要求任一模式匹配

    • 求反 not 模式要求模式不匹配

    • 關系模式要求輸入小于、大于、小于等于或大于等于給定常數。

    public static bool IsLetter(this char c) =>c is >= 'a' and <= 'z' or >= 'A' and <= 'Z';public static bool IsLetterOrSeparator(this char c) =>c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z') or '.' or ',';

    ?

    5調試和完成功能

    在 C# 9.0 中,已知創建對象的類型時,可在 new 表達式中省略該類型。 最常見的用法是在字段聲明中:

    private List<WeatherObservation> _observations = new();

    當需要創建新對象作為參數傳遞給方法時,也可使用目標類型 new。 請考慮使用以下簽名的 ForecastFor() 方法:

    public WeatherForecast ForecastFor(DateTime forecastDate, WeatherForecastOptions options)

    可按如下所示調用該方法:

    var forecast = station.ForecastFor(DateTime.Now.AddDays(2), new());

    好啦,關于c#的更新呢,暫時就這么多了,看著很長,其實很多咱們平時都已經使用到了,當然還有一些不太常用的我沒有去列舉,更多的內容,左下角點擊【閱讀原文】吧。




    BCVP開發者社區推薦

    歡迎你來

    總結

    以上是生活随笔為你收集整理的C#知多少 | 每个版本都更新了什么?的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。