本文由葡萄城技術團隊翻譯并首發
轉載請注明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者,
我們很高興今天.NET5.0正式發布,這是一個重要的版本—其中也包括了C# 9和F# 5大量新特性和優秀的改進,微軟和其他公司的團隊已經在生產和性能測驗環境中開始使用了,這些團隊向我們反饋的結果比較令人滿意,它證明了對性能提升及降低Web應用托管成本的機會有積極的表現,從預覽版1開始,我們一直在5.0上運行我們自己的網站,從我們目前的所見所聞來看,.NET5.0無需在升級上花費太多的精力就能帶來巨大的價值,對于你的下一個應用來說,這是一個很好的選擇,而且可以直接從早期的.NET Core版本升級,我們希望您在臺式機、筆記本電腦和云實體上正式開始使用它,
ASP.NET Core、EF Core、C#9和F#5也將在今天一同發布
您可以下載.NET5.0,適用于Windows、MacOS和Linux,適用于x86、x64、Arm32和Arm64,
- l 安裝程式和二進制檔案
- l Docker 容器 images
- l Linux package
- l 發行說明檔案
- l 已知的問題
- l GitHub問題跟蹤器
- l .NET 5.0貢獻者
對于Visual Studio用戶,您需要Visual Studio 16.8或更高的版本才能在Windows上使用.NET 5.0,在MacOS上使用最新版本的Visual Studio for Mac),Visual Studio Code的C#擴展也已經支持.NET5.0和C#9,
NET 5.0是我們的.NET統一之旅的第一個版本,我們構建.NET 5.0是為了讓更多的開發人員能夠將他們的.NET Framework代碼和應用程式遷移到.NET5.0,我們在5.0中也做了很多前期作業,以便Xamarin開發人員在發布.NET6.0時可以使用統一的.NET平臺,在后面的文章中會有更多關于.NET統一的內容,
這個版本是完全開源的第五個主要的.NET版本,現在,在GitHub上的DotNet org中,有大量的個人和公司(包括.NET Foundation企業贊助商)作為一個大型社區在.NET的各個方面共同作業,.NET5.0中的改進是許多人通過他們的努力及創新的想法構成的結果,所有這些都超出了微軟對該專案的管理,為此,我們向所有為.NET 5.0(以及之前的版本)做出貢獻的人表示 “萬分感謝”!
我們早在2019年5月就引入了.NET5.0,當時甚至設定了2020年11月的發布日期,結果我們如期發布了,為此要感謝團隊中的每一個人,是他們讓這一切成為現實! 2021年11月我們還將發布.NET 6.0,今后每年的11月我們都將發布新的.NET版本,
.NET 5.0亮點
在.NET5.0中有許多重要的改進:
l .NET5.0已經在dot.net和Bing.com上托管了幾個月,已經經過了數個月的實際測驗,
l 許多組件的性能都得到了極大的提高,在.NET5.0中的性能改進、.NET5.0中的ARM64性能和GRPC中都有詳細描述,
l C#9和F#5提供了新的語言改進,比如C# 9的頂級程式和記錄,而F# 5提供了互動式編程,.NET上函式式編程的性能得到了提升,
l .NET庫增強了Json序列化、正則運算式和HTTP(HTTP 1.1、HTTP/2)的性能,
l 改進了GC、分層編譯和其他方面,P95延遲有所降低,
l 通過ClickOnce客戶端發布應用程式,單檔案應用程式,減小的容器映像大小以及添加的Server Core容器映像,應用程式部署選項更好,
l Windows Arm64和WebAssembly擴展了平臺范圍,
我已經為.NET5.0寫了很多Demo,您可以看一下這些.NET5.0示例,以了解更多關于新的C#9和庫特性的資訊,
平臺和Microsoft支持
對于Windows、MacOS和Linux,.Net 5.0的平臺支持串列與.NET Core 3.1幾乎相同,如果您在受支持的作業系統上使用.NET Core 3.1,則應該能夠在該作業系統的大部分版本上采用.NET 5.0,在.NET 5.0中,最重要的新增功能是Windows Arm64,
.Net 5.0是當前版本,這意味著它將在.NET6.0發布后的三個月內得到支持,因此,我們預計到2022年2月中旬將支持.NET5.0,與.NET Core 3.1一樣,.NET6.0將是一個LTS版本,并將支持三年,
平臺統一的愿景
去年,我們分享了一個統一的.NET生態系統的愿景,它對您的價值在于,您將能夠使用同一組API、語言和工具來覆寫廣泛的應用型別,其中包括移動、云、桌面和物聯網,您可能已經意識到,現在您已經可以使用.NET面向廣泛的平臺,但可能工具和API在Web和Mobile之間并不總是相同的,或者并不總是同時發布的,
作為.NET5.0和6.0的一部分,我們正在將.NET的產品體驗盡可能的進行統一,同時使您能夠選擇您想要使用的.NET平臺的部分,如果你想以Mobile而不是WebAssembly為目標,你不需要下載WebAssembly工具,反之亦然,ASP.NET Core和WPF也是如此,您還可以通過更簡單的方式從命令列獲取所需的所有.NET工具以及構建和運行時包,我們正在為.NET平臺組件提供包管理器體驗(包括使用現有的包管理器),這對于很多場景來說都是很棒的,快速構建開發環境和CI / CD可能是最大的受益者,
實作這一愿景的第一步是整合.NET repos,包括Mono的一個大子集,擁有一個用于運行時和.NET庫的repo是在任何地方交付相同產品的前提條件,它還有助于進行廣泛的更改,這些更改會影響運行時和庫,而這些庫以前是有repo邊界的,一些人擔心,大規模回購將更難管理,事實證明并非如此,
在.NET 5.0版本中,Blazor是利用回購整合和.NET統一的最佳例子,Blazor WebAssembly的運行時和庫現在是從合并的 DotNet/runtime repo所構建的,例如,這意味著服務器上的Blazor WebAssembly和Blazor對List<T> 將使用完全相同的代碼,但在.NET5.0之前,Blazor并非如此,我們對Blazor WebAssembly采取的方法與我們在.NET6.0中使用Xamarin的方法非常相似,
.NET Framework仍然是受支持的Microsoft產品,并且每個新版本的Windows都將繼續支持它,我們去年宣布已經停止向.NET Framework添加新功能,并完成了向.NET Core添加.NET Framework API,這意味著現在是考慮將您的.NET Framework應用程式遷移到.NET Core的好機會,對于.NET Framework客戶端開發人員,.NET5.0支持Windows表單和WPF,我們從許多開發人員那里聽說,從.NET Framework移植非常簡單,對于.NET Framework服務器開發人員,您需要采用ASP.NET Core才能使用.NET 5.0,對于Web Forms開發人員,我們相信Blazor通過更高效、更現代化的實作提供了類似的開發體驗,WCF服務器和作業流用戶可以查看支持這些框架的社區專案,從.NET Framework移植到.NET Core檔案是一個很好的起點,這就是說,如果你對自己的體驗滿意,那么讓你的應用程式運行在.NET Framework上是一個很好的方法,
Windows團隊正致力于研究Reunion作為UWP及其相關技術的下一步,我們一直在與Reunion團隊合作,以確保.NET5.0及更高版本能夠很好地與WinUI和WebView2協同作業,
讓我們來看看5.0版本中的新特性,
語言
C#9和F#5是.NET5.0版本的一部分,包含在.NET5.0 SDK中,Visual Basic也包含在5.0 SDK中,它不包括語言更改,但進行了改進以支持.NET Core上的Visual Basic應用程式框架,
C#源代碼生成器是一項重要的C#編譯器新特性,從技術上講,它們不是C#9的一部分,因為它沒有任何語言語法,請參閱新的C#源代碼生成器示例,幫助您開始使用這一新功能,我們希望在.NET6.0及更高版本的.NET產品中更多地使用源代碼生成器,
為了親身試用新版本,我們部分人決定更新DotNet/iot Repo,以使用新的C#9語法并以.NET5.0嘗試目標,它使用頂級程式、記錄、模式和切換運算式,它也已更新,以利用.NET庫中完整的可為空的注釋集,我們還更新了.NET物聯網的檔案,我們將查看該repo中的幾個示例來探索C#9,
LED-BLINK程式是一個不錯的緊湊高級程式示例
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
您可以看到target-typed的使用以及new對controller變數的分配,,GpioController型別僅在賦值的左側定義,型別是在右手邊推斷出來的,這種新語法是var的另一種選擇,var的型別只顯示在賦值的右側,并通過關鍵字var在左側推斷,
通過定義方法并利用在相同或其他檔案中定義的型別,頂級程式也可能增加復雜性,CharacterLcd示例演示了其中一些功能,
邏輯和屬性模式
C# 9包括對新模型的支持,您可以在如下代碼中看到關于這個邏輯模式的示例,
| 1 2 3 4 5 6 |
|
另一種新模式是屬性模式,您可以在我的Mycroft資訊訪問6.0示例中看到幾個屬性檢查,以下代碼摘自PN532 RFID和NFC讀取器示例,
| 1 2 3 4 |
|
此代碼測驗pollingType(型別為byte[]?),為慷訓包含>15個位元組,這是回傳NULL之前需要測驗的兩個錯誤條件,也可以將此測驗撰寫為pollingType為慷訓{Length:>15},
我想再給你看兩個模型,第一個是Mcp25xxx CAN總線的邏輯模式,
| 1 2 3 4 5 6 |
|
第二個是Piezo蜂鳴器控制器中的邏輯模式,
| 1 2 3 4 5 6 7 8 9 10 11 12 |
|
記錄
C#9包括一個名為Record的新類,與常規類相比,它有許多優點,其中一半與更簡潔的語法有關,以下記錄取自Bh1745 RGB傳感器系結,
| 1 |
|
然后在同一檔案中稍晚一點使用它,語法很熟悉:
| 1 |
|
可為空性注釋的改進
現在,.NET庫完全為空性添加了注釋,這意味著如果您啟用nullability,您將從平臺獲得更多型別資訊來指導您使用該功能,目前,還沒有對.NET檔案進行完整的注釋,例如,String.IsNullOrEmpty(String)應該被注釋為接受一個字串?,而String.Split(Char[])的注釋是char[]?我們希望這個問題很快就能解決,完整的資訊可以在Soure.dot.net上找到,也可以通過Visual Studio中的F12元資料查找獲得,
System.Device.Gpio和Iot.Device.Bindings包(這兩個包的版本都是1.1.0)也作為此版本的一部分進行了注釋,使用了更新的.NET5.0注釋,這兩個庫都是多目標的,但是,我們使用5.0視圖為所有目標生成注釋,
我們還添加了新的注釋型別,大型類在從建構式呼叫的幫助器方法中實體化物件成員是很常見的,C#編譯器不能遵循對物件賦值的呼叫流程,當退出建構式時,它會認為該成員為空,并將使用CS8618發出警告,MemberNotNull屬性可以解決此問題,將該屬性應用于幫助器方法,然后,編譯器將看到您設定了此值,并意識到該方法是從建構式呼叫的,MemberNotNullWhen類似,
您可以使用以下代碼在BMxx80溫度傳感器中看到MemberNotNull的示例,
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
實際代碼使用條件編譯,這是因為該專案是多目標的,而該屬性僅在.NET5.0+中受支持,使用該屬性可以跳過運行時檢查(在建構式中),否則將需要這些檢查來滿足可空性要求,就像早期的.NET版本一樣,
工具類
我們改進了Windows Forms 設計器,使其能在.NET5.0及更高版本中運行,更改了支持WinRT的方式,并進行了其他改進,
Windows表單設計器
Windows表單設計器(用于.NET Core 3.1和.NET5.0)已在Visual Studio 16.8中進行了更新,現在支持所有Windows表單控制元件,設計器包括您指導的所有設計器功能,包括:拖放、選擇、移動和調整大小、控制元件的剪切/復制/粘貼/洗掉、與屬性視窗的集成、事件生成等,資料系結和對更廣泛的第三方控制元件集的支持很快就會到來,

.NET 5.0目標框架
在.NET5.0中,我們更改了用于目標框架的方法,以下專案檔案演示了新的.NET5.0目標框架,
| 1 2 3 4 5 6 7 8 |
|
新的net5.0表單比我們之前使用的樣式更緊湊、更直觀,此外,我們正在擴展目標框架以描述作業系統依賴關系,我們希望通過.NET 6.0中的Xamarin定位iOS和Android,從而推動了這一變化,
net5.0netcoreapp3.1
Windows桌面API(包括Windows表單、WPF和WinRT)僅在面向net5.0-windows時可用,您可以指定作業系統版本,如net5.0-Windows7或net5.0-windows10.0.17763.0(適用于Windows 2018年10月更新),如果您想要使用WinRT API,則需要瞄準Windows 10版本,
當使用新的net5.0-windows tfm時,跨平臺的場景可能會更具挑戰性,例如,System.Device.Gpio演示了一種用于管理Windows目標框架的模式,例如,如果您希望避免為Windows構建或避免在Linux上拉取Windows運行時包,
更新摘要:
- l Net5.0是.NET5.0的新目標框架Moniker (TFM),
- l Net5.0結合并取代了netcoreapp和netStandard tfms,
- l Net5.0支持.NET Framework兼容模式,
- l Net5.0-Windows將用于公開特定于Windows的功能,包括Windows Forms、WPF和WinRT API,
- l 特定于作業系統的TFMS可以包括作業系統版本號,如net6.0-ios14,
- l 像ASP.NET Core這樣的可移植API將可以在net5.0上使用,同樣的情況也適用于Net6.0的Xamarin Forms,
Visual Studio 16.8中的模板仍然以.NET Core 3.1為目標,用于控制臺、WPF和Windows表單應用程式,ASP.NET模板已更新為支持.NET5.0,我們將在Visual Studio 16.9中更新其余模板的模板,
WinRT Interop(重大更改)
關于以Windows API為目標的主題,我們已經轉向了一個新的模型,將WinRT API作為.NET5.0的一部分來支持,這包括呼叫API(雙向;CLR<==>WinRT),兩個型別系統之間的資料封送處理,以及要在型別系統或ABI邊界上被同等對待的型別的統一(即“投影型別”;IEnumerable和IIterable就是例子),
現有的WinRT互作業系統已作為.NET5.0的一部分從.NET運行時中移除,這是一個突破性的變化,這意味著使用WinRT和.NET Core 3.x的應用程式和庫需要重新構建,不能按原樣在.NET5.0上運行,使用WinRT API的庫需要多目標來管理.NET Core 3.1和.NET5.0之間的這種差異,
展望未來,我們將依靠WinRT團隊在Windows中提供的新CsWinRT工具,它生成基于C#的WinRT互操作程式集,這些程式集可以通過NuGet交付,這正是Windows團隊正在為Windows中的WinRT API所做的事情,任何想要使用WinRT(在Windows上)作為互作業系統的人都可以使用該工具,以將本機API公開給.NET或將.NETAPI公開給本機代碼,
CsWinRT工具在邏輯上類似于tlbimp和tlbexp,但要好得多,TLB工具依賴于.NET運行時中的大量COM互操作管道,CsWinRT工具只依賴于公共的.NETAPI,也就是說,C#9中的函式指標功能--在.NET5.0運行時中部分實作了--在一定程度上是受到CsWinRT工具需求的啟發,
這種新的WinRT互操作模型有幾個好處:
- l 它可以獨立于.NET運行時進行開發和改進,
- l 它與為iOS和Android等其他作業系統提供的基于工具的互作業系統是對稱的,
- l 該工具可以利用其他.NET特性(AOT、C#特性、IL鏈接),而這在以前的系統中不是一個選項,
- l 簡化了.NET運行時代碼庫,
使用WinRT API不需要添加NuGet參考,以Windows10TFM為目標--剛才在.NET5.0TFM一節中已經討論過了--已經足夠了,如果您的目標是.NET Core 3.1或更早版本,則需要參考WinRT包,您可以在System.Device.Gpio專案中看到此模式,
原生匯出
很長一段時間以來,我們一直要求為呼叫.NET代碼的本機二進制檔案啟用匯出,該場景的構建塊是托管對UnManagedCeller sOnlyAttribute的API支持,
此功能是創建更高級別體驗的構建塊,我們團隊中的Aaron Robinson一直致力于一個.NET Native Exports專案,該專案為將.NET組件發布為本機庫提供了更完整的體驗,我們正在尋找有關此功能的反饋,以幫助決定是否應將該方法包含在產品中,
.NET原生匯出專案使您能夠:
- l 公開自定義本機匯出,
- l 不需要像COM這樣的更高級別的互操作技術,
- l 跨平臺作業,
- 有一些現有的專案支持類似的場景,例如:
- l 不受管理的出口,
- l DllExport
多年來,我們在本機應用程式中看到了各種.NET托管模型,@rseanHall為此提出并實作了一種新穎的新模型,該模型利用了.NET應用程式托管層提供的所有內置應用程式功能(特別是加載依賴項),同時允許從本機代碼呼叫自定義入口點,這在很多情況下都是完美的,可以想象在從本機應用程式托管.NET組件的開發人員中變得流行起來,這在以前是不存在的,謝謝你的貢獻,@rseanHall,
兩個主要PR:
- l 啟用從應用背景關系呼叫Get_Runtime_Delegate,
- l 實作HDT_GET_Function_POINTER
事件管道
事件管道是我們在.NET Core 2.2中添加的一個新的子系統和API,它可以在任何作業系統上執行性能和其他診斷調查,在.NET5.0中,事件管道已得到擴展,使探查器能夠撰寫事件管道事件,此場景對于檢測以前依賴ETW(在Windows上)監視應用程式行為和性能的探查器至關重要,
現在可以通過事件管道獲得程式集加載資訊,這一改進是使類似的診斷功能(例如Fusion Log Viewer)成為.NET Framework的一部分的開始,現在,您可以使用以下命令,使用Dotnet-TRACE來收集此資訊:
dotnet-trace collect --providers Microsoft-Windows-DotNETRuntime:4:4 -- ./MyApp –my-arg 1
該作業流程在DotNet-TRACE檔案中進行了說明,您可以看到簡單測驗應用程式的程式集加載資訊,

Microsoft.Extensions.Logging
我們對Microsoft.Extensions.Logging庫中的控制臺日志提供程式進行了改進,現在,您可以實作自定義ConsoleForMatter來完全控制控制臺輸出的格式化和彩色化,格式化程式API通過實作VT-100(受大多數現代終端支持)轉義序列的子集來實作豐富的格式化,控制臺記錄器可以決議出不支持的終端上的轉義序列,允許您為所有終端撰寫一個格式化程式,
除了對定制格式化程式的支持之外,我們還添加了一個內置的JSON格式化程式,它可以將結構化的JSON日志發送到控制臺,
轉儲除錯
除錯托管代碼需要了解托管物件和構造,資料訪問組件(DAC)是運行時執行引擎的子集,它了解這些構造,可以在沒有運行時的情況下訪問這些托管物件,在Linux上收集的.Net Core行程轉儲現在可以在Windows上使用WinDBG或DotNet Dump Analyze進行分析,
我們還添加了對從MacOS上運行的.NET行程捕獲ELF轉儲的支持,由于ELF不是MacOS上的本機可執行檔案格式(像lldb這樣的本機除錯器不能處理這些轉儲),我們將其作為一種選擇加入的特性,要在MacOS上啟用轉儲收集支持,請設定環境變數COMPLUS_DbgEnableElfDumpOnMacOS=1,生成的轉儲可以使用DotNet Dump Analyze進行分析,
列印環境資訊
隨著.NET擴展了對新作業系統和芯片體系結構的支持,人們有時想要一種列印環境資訊的方式,我們創建了一個簡單的.NET工具來完成此任務,名為dotnet-runtimeinfo,
您可以使用以下命令安裝和運行該工具,
| 1 2 |
|
該工具為您的環境生成以下形式的輸出,
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
運行時和庫
在運行時和庫中有很多改進
RyuJIT的代碼質量改進
這個版本對JIT有很多改進,我在以前的.NET5.0預覽帖中分享了其中的許多改進,在這篇文章中,我提升了來自社區的改變,
- l 將xmm用于堆疊prolog-dotnet/Runtime#32538-更改為x86/x64 prolog零位調整代碼,改進:JSON;TechEmpower,致謝:本·亞當斯,
- l 用于ARM64的Vectorise位陣列-Dotnet/Runtime#33749-BitArray類已更新,包括使用ARM64內部結構的ARM64硬體加速實作,BitArray的性能改進非常顯著,感謝@Gnbrkm41,
- l 動態通用詞典擴展特性dotnet/運行時#32270-一些(可能是大多數?),基于改進了運行庫用來存盤有關泛型型別和方法的資訊的低級(本機代碼)字典的實作,泛型的使用現在有了更好的性能(最初的性能發現),有關更多資訊,請參見Perf:COLLECTION COUNT()在Core中比CLR慢,錯誤報告歸功于@RealDotNetDave,
- l Implementate Vector.Celing/Vector.Floor Dotnet/Runtime#31993-按照API提案,使用x64和Arm64內部函式實作Vector.Celing/Vector.Floor,感謝@Gnbrkm41,
- l TailCall助手的新的、更快的、可移植的實作,來源:Jakob Botsch Nielsen(.NET團隊實習生),來自@dsymetweet的反應,
- l 添加VectorTableList和TableVectorExtension內部-Credit:@TamarChristinaArm(ARM Holdings),
- l 使用新的硬體內部組件BSF/BSR-Credit@saucecontrol提高英特爾架構性能,
- l 實作向量{Size}.AllBitsSet-Credit@Gnbrkm41,
- l 允許逃避一些邊界檢查-Credit@Nathan-Moore
垃圾收集器GC
在GC中進行了以下改進,
- l 卡片標記竊取-dotnet/coreclr#25986-服務器GC(在不同執行緒上)現在可以作業竊取,同時標記由老一代物件持有的0/1類物件,這意味著,在某些GC執行緒標記時間比其他執行緒長得多的情況下,短暫的GC暫停會更短,
- l 引入固定物件堆-DotNet/Runtime#32283-添加固定物件堆(PoH),這個新堆(大物件堆(LOH)的對等體)將允許GC單獨管理固定物件,從而避免固定物件對世代堆的負面影響,
- l 允許從空閑串列分配大物件,同時后臺使用空閑串列清理啟用了SOH的LOH分配,而BGC正在清理SOH,以前,這只在LOH上使用段末尾空間,這允許更好地使用堆,
- l 后臺GC掛起修復-dotnet/coreclr#27729-掛起修復減少了bgc和用戶執行緒掛起的時間,這減少了在GC發生之前掛起托管執行緒所需的總時間,Dotnet/coreclr#27578也促成了同樣的結果,
- l 修正了擴展塢中的命名組組處理,增加了對從命名組組讀取限制的支持,以前我們只讀全球版本,
- l 優化矢量化排序-Dotnet/Runtime#37159-GC中的矢量化標記串列排序,減少了短暫的GC暫停時間(也包括Dotnet/Runtime#40613),
- l 世代感知分析-DotNet/Runtime#40322-世代感知分析,允許您確定哪些老一代物件保留在年輕一代物件上,從而使它們存活下來,并導致短暫的GC暫停時間,
- l 優化分解GC堆記憶體頁面-Dotnet/Runtime#35896-優化分解,更好地分解邏輯,對于服務器GC來說,完全退出了“停止世界”階段,從而減少了阻塞GC的暫停時間,
現在,GC通過EgGetGCMmemyInfo方法公開最新集合的詳細資訊,GCMmemyInfo結構提供有關機器記憶體、堆記憶體和您指定的GC型別的最新集合或最新集合的資訊-臨時GC、完全阻塞GC或后臺GC,
使用這個新API的最有可能的用例是日志記錄/監視,或者向加載器平衡器指示機器應該停止旋轉以請求完整的GC,它還可以通過減小快取大小來避免容器硬限制,
另一個小而有效的改變是將昂貴的重置記憶體操作推遲到記憶體不足的情況,我們預計策略中的這些更改將降低GC延遲(以及總體上的GC CPU使用率),
Windows ARM64
現在,.NET應用程式可以在Windows Arm64上本地運行,在此之前,我們在.NETCore3.0中添加了對Linux Arm64的支持(對Glibc和MUSL的支持),使用.NET 5.0,您可以在Windows Arm64設備(如Surface Pro X)上開發和運行應用程式,您已經可以在Windows Arm64上運行.NET Core和.NET Framework應用程式,但需要通過x86仿真,這是可行的,但是原生ARM64執行的性能要好得多,
針對ARM64的MSI安裝程式是此版本的最終更改之一,您可以在下圖中看到.NET5.0SDK安裝程式,

NET 5.0 SDK目前不包含Windows Arm64上的Windows桌面組件-Windows Forms和WPF,這一變化最初是在.NET5.0預覽版8中發布的,我們希望在5.0服務更新中添加Windows Arm64的Windows桌面包,我們目前還沒有可以分享的日期,在此之前,Windows Arm64支持SDK、控制臺和ASP.NET Core應用程式,但Windows桌面組件不支持,
ARM64性能
一年多來,我們在提高ARM64性能方面投入了大量資金,我們致力于使ARM64成為一個基于.NET的高性能平臺,這些改進同樣適用于Windows和Linux,平臺可移植性和一致性一直是.NET令人信服的特點,這包括無論您在哪里使用.NET都能提供出色的性能,在.NET Core 3.x中,ARM64的功能與x64不相上下,但缺少一些關鍵的性能特性和投資,我們已經在.NET5.0中解決了這個問題,正如在.NET5.0中的ARM64性能中所描述的那樣,
改進之處在于:
- l 調整ARM64的JIT優化(示例),
- l 啟用并利用ARM64硬體特性(示例),
- l 調整ARM64庫中的關鍵性能演算法(例如),
有關更多詳細資訊,請參見在.NET5.0中提高Arm64性能,
硬體內部屬性是我們在.NET Core3.0中添加的一個低級性能特性,當時,我們增加了對x86-64指令和芯片的支持,作為.NET5.0的一部分,我們正在擴展該功能以支持ARM64,僅僅創建內部結構并不能提高性能,它們需要在性能關鍵型代碼中使用,我們在.NET5.0的.NET庫中廣泛利用了Arm64的內部特性,您也可以在自己的代碼中做到這一點,盡管您需要熟悉CPU指令才能做到這一點,
我將用一個類比來解釋硬體內部是如何作業的,在很大程度上,開發人員依賴于.NET中內置的型別和API,比如string.Split或HttpClient,這些API通常通過P/Invoke功能利用本地作業系統API,P/Invoke支持高性能的本機互操作,并在.NET庫中為此廣泛使用,您可以自己使用相同的功能來呼叫本機API,硬體內部功能類似,不同之處在于它們不是呼叫作業系統API,而是使您能夠在代碼中直接使用CPU指令,它大致相當于C++內部函式的.NET版本,硬體本質最好被認為是一種CPU硬體加速功能,它們提供了非常實實在在的好處,現在是.NET庫性能基礎的關鍵部分,并負責您可以在.NET5.0性能帖子中讀到的許多好處,與C++相比,當.NET內部函式被AOT編譯成隨時可以運行的檔案時,內部函式沒有運行時性能損失,
注意:Visual C++編譯器具有類似的內部特性,您可以直接將C++與.NET硬體內部功能進行比較,如果您在System.Rune me.Intrinsics.X86.Avx2、x64(AMD64)內部功能串列和英特爾內部功能指南中搜索_mm_i32ather_ep32,就可以看到這一點,你會看到很多相似之處,
我們在5.0中對ARM64的性能進行了第一次重大投資,并將在后續版本中繼續這方面的努力,我們直接與ARM Holdings的工程師合作,確定產品改進的優先順序,并設計最充分利用ARMv8 ISA的演算法,其中一些改進將為ARM32帶來價值,然而,我們并沒有將獨特的努力應用于ARM32,如果你使用的是Raspberry Pi,如果你安裝了新的Arm64版本的Raspberry Pi OS,你會享受到這些改進,
我們預計蘋果將在任何時候發布新的蘋果硅基Mac電腦,我們已經有了針對Apple Silicon的.NET6.0的早期版本,并一直在與蘋果的工程師合作,幫助為該平臺優化.NET,我們在Apple Silicon(Credit@Sickler)上也有一些早期的社區參與,
P95+延遲
我們看到越來越多的大型面向互聯網的網站和服務托管在.NET上,雖然有很多合理的關注點放在每秒請求數(RPS)指標上,但我們發現沒有大的網站所有者問我們這個問題或要求數百萬的RPS,然而,我們聽說了很多關于延遲的事情,特別是關于改善P95或P99延遲的問題,通常,為站點配置的機器或核心的數量(以及最大的成本驅動因素)是根據達到特定的P95指標(而不是P50)來選擇的,我們認為延遲是真正的“金錢指標”,
我們在Stack Overflow的朋友們在分享他們服務上的資料方面做得很好,他們的一位工程師尼克·克雷弗(Nick Craver)最近分享了他們在遷移到.NET Core后看到的延遲改進:
鎖定物件一直是GC性能的長期挑戰,特別是因為它們加速(或導致)記憶體碎片,我們為固定物件添加了一個新的GC堆,固定物件堆基于這樣的假設,即行程中固定的物件非常少,但它們的存在會造成不成比例的性能挑戰,將固定物件(尤其是那些由.NET庫作為實作細節創建的物件)移動到一個獨特的區域是有意義的,這樣會使世代GC堆中只有很少的固定物件,甚至沒有固定物件,因此性能會大大提高,
最近,我們一直在應對大中華區長期存在的挑戰,DotNet/Runtime#2795應用了一種新的GC靜態掃描方法,在確定GC堆物件的活躍度時避免了鎖爭用,Dotnet/Runtime#25986使用了一種新演算法,用于在垃圾收集的標記階段跨核心平衡GC作業,這應該會增加大堆垃圾收集的吞吐量,進而減少延遲,
提高分層編譯的性能
我們一直致力于改進多版本的分層編譯,我們繼續將其視為一個關鍵的性能特性,無論是啟動性能還是穩態性能,在這個版本中,我們對分層編譯做了兩大改進,
分層編譯的主要機制是呼叫計數,一旦一個方法被呼叫n次,運行庫就會要求JIT以更高的質量重新編譯該方法,從我們最早的性能分析中,我們知道呼叫計數機制太慢,但沒有看到一個簡單的方法來解決這個問題,作為.NET5.0的一部分,我們改進了分層JIT編譯使用的呼叫計數機制,以平滑啟動時的性能,在過去的版本中,我們看到了在行程生命周期的前10-15秒(主要是Web服務器)中出現的不可預測的性能報告,這個問題現在應該得到解決,
我們發現的另一個性能挑戰是對帶有回圈的方法使用分層編譯,根本問題是,您可以使用一個回圈多次的冷方法(只呼叫一次或幾次;$lt;n),我們稱這種病態場景為“冷方法;熱回圈”,很容易想象這種情況會發生在應用程式的Main方法中,因此,默認情況下,我們禁用了具有回圈的方法的分層編譯,相反,我們允許應用程式選擇使用帶回圈的分層編譯,PowerShell是在看到某些場景的高個位數性能改進后選擇這樣做的應用程式,
為了更好地處理具有回圈的方法,我們實作了堆疊上替換(OSR),這類似于Java虛擬機具有的同名功能,OSR使當前正在運行的方法執行的代碼能夠在方法執行程序中重新編譯,而這些方法是活動的“堆疊上”,這一功能目前還處于試驗階段和選擇加入階段,并且僅在x64上,
要使用OSR,必須啟用多項功能,PowerShell專案檔案是一個很好的起點,您會注意到,分層編譯和所有快速JIT功能都已啟用,此外,需要將COMPLUS_TC_OnStackReplace環境變數設定為1,
或者,您也可以設定以下兩個環境變數,假設所有其他設定都有其預設值:
COMPLUS_TC_QuickJitForLoops=1,
COMPLUS_TC_OnStackReplace=1,
我們不打算在.NET5.0中默認啟用OSR,也還沒有決定是否會在生產中支持它,
在Windows上支持ICU
我們使用ICU庫來支持Unicode和全球化,以前只在Linux和MacOS上使用,我們現在在Windows 10上使用相同的庫,這一更改使得全球化API的行為在Windows 10、MacOS和Linux之間保持一致,例如特定于區域性的字串比較,我們還將ICU與Blazor WebAssembly配合使用,
將System.DirectoryServices.Protooles擴展到Linux和MacOS
我們一直在添加對System.DirectoryServices.Protooles的跨平臺支持,這包括對Linux的支持和對MacOS的支持,Windows支持是預先存在的,
協議是一個比System.DirectoryServices更低級的API,可以支持(或可以用來支持)更多場景,System.DirectoryServices包含僅限Windows的概念/實作,因此它不是跨平臺的明顯選擇,這兩個API集都支持控制目錄服務服務器并與其互動,如LDAP或Active Directory,
System.Text.Json
System.Text.Json在.NET5.0中得到了顯著改進,以提高性能和可靠性,并使熟悉Newtonsoft.Json的人們更容易采用,它還支持將JSON物件反序列化為記錄,
如果您正在考慮使用System.Text.Json作為Newtonsoft.Json的替代方案,您應該查看遷移指南,本指南闡明了這兩個API之間的關系,Json旨在涵蓋許多與Newtonsoft.Json相同的場景,但它并不是要替代流行的JSON庫,也不是要實作與流行的JSON庫相同的功能,我們試圖在性能和可用性之間保持平衡,在我們的設計選擇中偏向于性能,
HttpClient擴展方法
JsonSerializer擴展方法現在在HttpClient上公開,極大地簡化了這兩個API的結合使用,這些擴展方法消除了復雜性,并為您處理了各種場景,包括處理內容流和驗證內容媒體型別,Steve Gordon很好地解釋了在System.Net.Http.Json中使用HttpClient發送和接收JSON的好處,
下面的示例將天氣預報JSON資料反序列化為Forecast記錄,使用新的
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
這段代碼很緊湊!它依賴于C#9中的頂級程式和記錄以及新的GetFromJsonAsync<T>()擴展方法,在如此接近的情況下使用Foreach和Await可能會讓您懷疑,我們是否要添加對JSON物件流的支持,我真的希望如此,
您可以在自己的機器上嘗試此功能,以下.NET SDK命令將使用WebAPI模板創建天氣預報服務,默認情況下,它將在以下網址公開服務:https://localhost:5001/WeatherForecast.,這與示例中使用的URL相同,
| 1 2 3 |
|
確保您已經運行了DotNet dev-certs https--首先信任,否則客戶端和服務器之間的握手將不起作用,如果遇到問題,請參閱信任ASP.NET核心HTTPS開發證書,
然后,您可以運行上一個示例,
| 1 2 3 4 5 6 7 8 |
|
改進了對不可變型別的支持
定義不可變型別有多種模式,記錄只是最新的記錄,JsonSerializer現在支持不可變型別,
在本例中,您將看到帶有不可變結構的序列化,
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
注意:JsonConstructor屬性是指定要與結構一起使用的建構式所必需的,對于類,如果只有一個建構式,則不需要該屬性,記錄也是如此,
它會產生以下輸出:
| 1 2 3 4 5 6 |
|
支持記錄
JsonSerializer對記錄的支持幾乎與我剛才向您展示的對不可變型別的支持相同,我想在這里展示的不同之處在于將JSON物件反序列化為一個記錄,該記錄公開了一個引數化的建構式和一個可選的init屬性,
以下是程式片段,包括Record定義:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
它會產生以下輸出:
| 1 2 3 |
|
改進了對Dictionary<K,V>的支持
JsonSerializer現在支持使用非字串鍵的字典,您可以在下面的示例中看到這是什么樣子,在.NET Core 3.0中,此代碼進行編譯,但會引發NotSupportdException例外,
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
它會產生以下輸出,
| 1 2 3 |
|
對欄位的支持
JsonSerializer現在支持欄位,這一變化是由@YohDeadfall貢獻的,謝謝!,
您可以在下面的示例中看到這是什么樣子,在.NET Core 3.0中,JsonSerializer無法序列化或反序列化使用欄位的型別,對于具有欄位且無法更改的現有型別,這是一個問題,有了這一變化,這就不再是問題了,
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
它會產生以下輸出,
| 1 2 3 4 5 6 |
|
保留JSON物件圖中的參考
JsonSerializer增加了對在JSON物件圖中保留(回圈)參考的支持,它通過存盤ID來實作這一點,當JSON字串被反序列化為物件時,這些ID可以重新組成,
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
|
性能
在.NET5.0中,JsonSerializer的性能得到了顯著提高,Stephen Toub在他的.NET5帖子中談到了JsonSerializer的一些性能改進,我還在.NET5.0RC1文章中更詳細地介紹了Json的性能,
應用程式部署
在撰寫或更新應用程式之后,您需要部署它以使您的用戶受益,這可能是到Web服務器、云服務或客戶端計算機,也可能是使用Azure DevOps或GitHub操作等服務的CI/CD流的結果,
我們努力提供一流的部署功能,自然地與應用程式型別保持一致,對于.NET5.0,我們專注于改進單檔案應用程式,減少停靠多階段構建的容器大小,并為使用.NET Core部署ClickOnce應用程式提供更好的支持,
容器
我們認為容器是最重要的云趨勢,并在這方面投入了大量資金,我們正在以多種方式投資容器,在.NET軟體堆疊的多個級別上,首先是我們對基本面的投資,這越來越多地受到容器場景和部署容器應用的開發者的影響,
我們正在讓與集裝箱管弦樂團的合作變得更容易,我們已經添加了OpenTelemeter支持,這樣您就可以從您的應用程式中捕獲分布式跟蹤和指標,DotNet-monitor是一種新工具,旨在作為從.NET行程訪問診斷資訊的主要方式,特別是,我們已經開始構建dotnet-monitor的容器變體,您可以將其用作應用程式側車,最后,我們正在構建DotNet/Tye,以此來提高微服務開發人員的作業效率,包括開發和部署到Kubernetes環境,
NET運行時現在支持cgroup v2,我們預計它將在2020年后成為與容器相關的重要API,Docker目前使用的是cgroup v1(已經被.NET支持),相比之下,cgroup v2比cgroup v1更簡單、更高效、更安全,您可以通過我們2019年Docker更新了解更多關于cgroup和Docker資源限制的資訊,Linux發行版和容器運行時正在添加對cgroup v2的支持,一旦cgroup v2環境變得更加普遍,.Net 5.0將在cgroup v2環境中正常作業,這歸功于Omair Majid,他在Red Hat支持.NET,
除了Nano Server,我們現在還發布Windows Server Core鏡像,我們添加了Server Core,因為我們收到了客戶的反饋,他們想要一個與Windows Server完全兼容的.NET映像,如果你需要這個,那么這張新照片就是為你準備的,支持Windows Server 2019長期服務渠道(LTSC)、.NET5.0和x64的組合,我們還進行了其他更改,以減小Windows服務器核心映像的大小,這些改進帶來了很大的不同,但都是在Windows Server 2019發布之后做出的,然而,它們將使下一個Windows Server LTSC版本受益,
作為使用“.NET”作為產品名稱的一部分,我們現在將.NET Core 2.1、3.1和.NET5.0鏡像發布到mcr.microsoft.com/dotnet系列的Repos中,而不是發布到mcr.microsoft.com/dotnet/core,我們將繼續將.NET Core 2.1和3.1雙重發布到以前的位置,同時支持這些版本,.Net 5.0影像將僅發布到新位置,請相應地更新您的From陳述句和腳本,
作為.NET5.0的一部分,我們將SDK鏡像重新建立在ASP.NET鏡像之上,而不是構建包-dep,以顯著減小您在多階段構建場景中拉取的聚合鏡像的大小,
此更改對于多階段構建有以下好處,其中包含一個示例Dockerfile:
Ubuntu 20.04 Focus的多階段構建成本:
| Pull Image | Before | After |
| sdk:5.0-focal | 268 MB | 232 MB |
| aspnet:5.0-focal | 64 MB | 10 KB (manifest only) |
減少了約: 100 MB (-30%)
Debian 10 Buster的多階段構建成本:
| Pull Image | Before | After |
| sdk:5.0 | 280 MB | 218 MB |
| aspnet:5.0 | 84 MB | 4 KB (manifest only) |
減少了約: 146 MB (-40%)
有關更多詳細資訊,請參見Dotnet/Dotnet-docker#1814,
此更改有助于多階段構建,其中SDK和您的目標aspnet或運行時鏡像的版本相同(我們預計這是常見的情況),在進行此更改時,(例如)aspnet拉入將是不可行的,因為您將通過最初的SDK拉入拉出aspnet層,
我們對阿爾卑斯和Nano服務器做了類似的更改,阿爾卑斯和Nano服務器都沒有Buildpack-dep鏡像,但是,阿爾卑斯和Nano Server的SDK鏡像之前并不是在ASP.NET鏡像之上構建的,我們解決了這個問題,你將會看到阿爾卑斯和Nano服務器以及5.0版本在多階段構建方面都獲得了巨大的成功,
單檔案應用程式
單個檔案應用程式作為單個檔案發布和部署,該應用程式及其依賴項都包含在該檔案中,當應用程式運行時,依賴項直接從該檔案加載到記憶體中(不會影響性能),
在.NET5.0中,單檔案應用程式主要集中在Linux上(稍后會詳細介紹),它們可以是依賴于框架的,也可以是獨立的,依賴于全球安裝的.NET運行時,依賴于框架的單個檔案應用程式可能非常小,自包含的單檔案應用程式較大(由于帶有運行庫),但不需要在安裝前安裝.NET運行庫,因此可以直接運行,一般來說,依賴于框架對開發和企業環境都有好處,而對于ISV來說,自包含通常是更好的選擇,
我們用.NET Core 3.1制作了一個版本的單檔案應用程式,它將二進制檔案打包到單個檔案中進行部署,然后將這些檔案解壓縮到一個臨時目錄中以加載和執行它們,在某些情況下,這種方法可能會更好,但我們希望我們為5.0構建的解決方案會更好,這是一個值得歡迎的改進,
要創建真正的單一檔案解決方案,我們需要克服多個障礙,關鍵任務是創建一個更復雜的應用程式捆綁器,并教導運行庫從二進制資源加載程式集,我們還遇到了一些無法逾越的障礙,
在所有平臺上,我們都有一個稱為“apphost”的組件,這是成為可執行檔案的檔案,例如Windows上的myapp.exe或基于Unix的平臺上的./myapp,對于單一檔案應用程式,我們創建了一個新的apphost,我們稱之為“超級主機”,它具有與常規apphost相同的角色,但還包括運行時的靜態鏈接副本,超級主機是我們單一檔案方法的一個基本設計點,這個模型就是我們在帶有.NET5.0的Linux上使用的模型,由于各種作業系統的限制,我們無法在Windows或MacOS上實作這種方法,我們在Windows或MacOS上沒有超級主機,在這些作業系統上,本地運行時二進制檔案(大約3個)位于單個檔案應用程式旁邊(導致“不是單個檔案”),我們將在.NET6.0中重新討論這種情況,然而,我們預計我們遇到的問題仍然具有挑戰性,
您可以使用以下命令來生成單檔案應用程式,
l 依賴框架的單檔案APP:
n DotNet PUBLISH-r Linux-x64--自含式FALSE/p:PublishSingleFile=TRUE,
l 自含式單檔案APP:
n DotNet PUBLISH-r Linux-x64--自含式TRUE/p:PublishSingleFile=TRUE
您還可以使用專案檔案配置單個檔案發布,
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
您可以嘗試使用程式集修剪來減小應用程式的大小,它可能會通過過度修剪來破壞應用程式,因此建議在使用此功能后徹底測驗您的應用程式,程式集調整還會移除提前編譯的讀到運行本機代碼(用于被調整的程式集),這主要是為了提高性能,您需要在裁剪之后測驗應用程式的性能,通過使用PublishReadyToRun屬性(并設定為true),您可以在裁剪后即可運行編譯您的應用程式,
注:
- l 應用程式是特定于作業系統和架構的,您需要發布每種配置(Linuxx64、LinuxArm64、Windowsx64、…),,
- l 組態檔(如*.runtimeconfig.json)包含在單個檔案中,如果需要,您可以在單個檔案旁邊放置額外的組態檔(可能是為了測驗),
- l 默認情況下,單個檔案中不包括.pdb檔案,您可以使用<DebugType>Embed</DebugType>屬性啟用PDB嵌入,
- l IncludeNativeLibrariesForSelfExtract屬性可用于在Windows和MacOS上嵌入本機運行時二進制檔案,但它們必須在運行時解壓縮到臨時存盤中,不建議在一般情況下使用此功能,
ClickOnce
多年來,ClickOnce一直是流行的.NET部署選項,現在,它被.NET Core 3.1和.NET5.0 Windows應用程式支持,當我們將Windows表單和WPF支持添加到.NET Core 3.0中時,我們知道很多人會希望使用ClickOnce進行應用程式部署,在過去的一年里,.NET和Visual Studio團隊共同努力,在命令列和Visual Studio中啟用ClickOnce發布,
從專案一開始,我們就有兩個目標:
- l 在Visual Studio中為ClickOnce啟用熟悉的體驗,
- l 使用MSBuild或MAGE工具,通過命令列流為ClickOnce發布啟用現代CI/CD,
- 用圖片向你展示這種體驗是最容易的,
讓我們從Visual Studio體驗開始,它以專案發布為中心,

我們目前支持的主要部署模式是依賴于框架的應用程式,很容易依賴于.NET桌面運行時(即包含WPF和Windows表單的桌面運行時),如果需要,ClickOnce安裝程式將在用戶計算機上安裝.NET運行時,我們還打算支持獨立和單一檔案應用程式,

您可能會想,您是否仍然能夠利用ClickOnce脫機和更新功能,可以,停那兒吧,

MAGE最大的變化是它現在是一個.NET工具,發布在NuGet上,這意味著你不需要在你的機器上安裝任何特殊的東西,您只需要.NET5.0SDK,然后就可以將MAGE安裝為一個.NET工具,您也可以使用它發布.NET Framework應用程式,但是,SHA1簽名和部分信任支持已被移除,
MAGE安裝命令如下:
dotnet tool install -g Microsoft.DotNet.Mage
在您制作并分發了ClickOnce安裝程式之后,您的用戶將看到熟悉的ClickOnce安裝對話框,

當您使更新可用時,您的用戶將看到更新對話框,

最后總結
Net 5.0是另一個大版本,它應該會改進你使用.NET的許多方面,我們已經實作了一系列的改進,從單檔案應用程式到性能,從Json序列化的可用性到ARM64的支持,雖然今天可能是您使用.NET5.0的第一天,但我們在微軟的產品中運行.NET5.0已經有幾個月了,我們相信,它已準備好供您使用、運營您的業務并為您的應用程式提供動力,C#9和F#5中的新語言改進應該會使您的代碼更具表現力,更易于撰寫,對于您現有的應用程式來說,.Net 5.0也是一個很好的選擇,在許多情況下,您可以毫不費力地升級,
如果您對性能感興趣,您可能會對我們在TechEmpower基準測驗方面的進展感興趣,回過頭來看,您可以看到.NETCore3.1在最新一輪第19輪中的表現相當不錯,我們期待著在即將到來的第20輪中看到.NET5.0,當第20輪最終確定并發布時,新的排名將是值得關注的,
在.NET5.0中的改進是許多人共同努力的結果,他們在GitHub上,在世界各地,在多個時區協同作業,感謝為這一版本做出貢獻的每一個人,別擔心,有很多機會可以貢獻自己的力量,NET5.0版本已經結束,但是下一個版本已經開始了,
Net 5.0是另一個大版本,它應該會改進你使用.NET的許多方面,我們已經實作了一系列的改進,從單檔案應用程式到性能,從Json序列化的可用性到ARM64的支持,雖然今天可能是您使用.NET5.0的第一天,但我們在微軟的產品中運行.NET5.0已經有幾個月了,我們相信,它已準備好供您使用、運營您的業務并為您的應用程式提供動力,C#9和F#5中的新語言改進應該會使您的代碼更具表現力,更易于撰寫,對于您現有的應用程式來說,.Net 5.0也是一個很好的選擇,在許多情況下,您可以毫不費力地升級,
如果您對性能感興趣,您可能會對我們在TechEmpower基準測驗方面的進展感興趣,回過頭來看,您可以看到.NETCore3.1在最新一輪第19輪中的表現相當不錯,我們期待著在即將到來的第20輪中看到.NET5.0,當第20輪最終確定并發布時,新的排名將是值得關注的,
在.NET5.0中的改進是許多人共同努力的結果,他們在GitHub上,在世界各地,在多個時區協同作業,感謝為這一版本做出貢獻的每一個人,別擔心,有很多機會可以貢獻自己的力量,NET5.0版本已經結束,但是下一個版本已經開始了,
本文是由葡萄城技術開發團隊發布,轉載請注明出處:葡萄城官網
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/214378.html
標籤:其他
