.NET 6 Preview 4 已發(fā)布,有這些新功能!
.NET 6 Preview 4 Released
我們很高興地發(fā)布 .NET 6 Preview 4。現(xiàn)在,我們到 .NET 6 正式發(fā)布尚有一半。現(xiàn)在是再次瀏覽.NET 6 全部內容的好時機,就像第一篇預覽文章一樣。許多功能處于最終形式,而其他功能也將很快發(fā)布,因為已經(jīng)為發(fā)布提供了基礎構建塊。Preview 4 為在 11月交付最終的 .NET 6 版本奠定了堅實的基礎,并提供了完整的功能和體驗。如果您尚未在環(huán)境中嘗試過.NET 6,它也已準備好進行實際測試。
說到最終版本,我們現(xiàn)在有個會議!為 .NET Conf 2021預訂11月9日至11日。我們將在9日發(fā)布.NET 6,其中將進行許多深入的演講和演示,向您介紹有關 .NET 6 的所有知識。
您可以下載適用于Linux,macOS和Windows的 .NET 6 Preview 4。
安裝程序和二進制文件 容器鏡像 Linux軟件包 發(fā)布說明 已知的問題 GitHub問題追蹤
有關 Web和數(shù)據(jù)訪問方案的新增功能,請參閱ASP.NET Core和EF Core帖子以獲取更多詳細信息。還有一個新的 .NET MAUI 帖子,描述了新的客戶端應用程序體驗,以及一個 Hot reload 帖子,描述了開發(fā)人員生產(chǎn)力的新方法。
.NET 6 已通過 Visual Studio 16.11 和Visual Studio for Mac 8.9進行了測試。如果您想在Visual Studio嘗試.NET 6,我們建議您使用這些版本。
BUILD 2021
微軟BUILD大會就在這個星期。它是免費的,并且可以在網(wǎng)絡上觀看直播。現(xiàn)在注冊還為時不晚。
您一定想要了解這些介紹,其中包括有關.NET 6的大量討論和演示,這些演示向您展示了新功能和現(xiàn)在的可能。
.NET進行現(xiàn)代應用程序開發(fā)的未來 .NET 6深入探討;有什么新東西,還將有哪些新東西 .NET團隊 “專家提問”
.NET 6 主題
我們從2020年末開始在GitHub上規(guī)劃.NET 6。我們在廣泛的主題中確定了八個主題,包括行業(yè)方案,支持和教育。主題占我們發(fā)布工作的一半到四分之三。有許多項目沒有達到主題的水平或意義重大但沒有主題意義的項目(例如支持Apple Silicon設備)。
以下是.NET 6主題,每個主題都有一個句子摘要。它們以與顯示在themesof.net中相同的順序列出。
.NET吸引新的開發(fā)人員和學生-通過清晰的文檔,更簡單的代碼模型(需要學習的文件和概念更少)以及為測試和生產(chǎn)環(huán)境部署的方式,在Visual Studio產(chǎn)品中提供非常簡單的體驗。 .NET具有出色的客戶端應用程序開發(fā)體驗-提供了一個跨平臺的客戶端應用程序基礎,可以無縫地迎合桌面,移動和 Web開發(fā)人員,并可以在 Blazor 和 Xamarin 等現(xiàn)有應用程序類型的基礎上進行擴展。 .NET被認為是構建云原生應用程序的引人注目的框架-提供主要針對性能和可觀察性的基本云原生功能,改進與云原生和容器生態(tài)系統(tǒng)的集成以及演示了很多內容的云原生組件(yarp),它通過重要的云使用用例展示了 .NET 很大的價值。 企業(yè)和LTS-為將.NET與重要的應用程序結合使用提供更簡單,更可預測的應用模型,并更好地滿足大型企業(yè)和政府客戶的需求。 通過提高質量,信心和支持來發(fā)展 .NET 生態(tài)系統(tǒng)—建立長期的社區(qū)協(xié)作,旨在將社區(qū)開發(fā)人員的水平提升到與 Microsoft 類似的水平,并(反過來)提供新功能和新體驗使得企業(yè)開發(fā)人員更容易依賴社區(qū)開放源代碼項目中的庫,這些庫不一定與大公司有關聯(lián)或由大公司支持。 改善.NET開發(fā)人員的 inner-loop 性能-改善開發(fā)人員的工作效率,包括提高構建性能,熱重啟和熱重載。 使用運行時執(zhí)行信息(PGO)改善啟動和吞吐量—提供一種新模型來基于可用于更快啟動,更高吞吐量和更小的二進制文件的運行時信息提高性能。 滿足開發(fā)人員的期望-根據(jù)反饋在整個.NET產(chǎn)品中進行改進,并啟用具有現(xiàn)有功能的新方案。
以下帖子將更詳細地討論其中一些主題:
.NET 6預覽版1 .NET 6預覽版2 關于 PGO 的對話
統(tǒng)一 .NET 平臺
在過去的帖子和會議上,我們已經(jīng)討論了很多有關.NET統(tǒng)一的話題,但是主題中卻缺少它。平臺統(tǒng)一已融入到我們所做的所有事情中,并且不需要自己的主題。可以將其視為超出所列主題之外的一個大型主題。它貫穿多個主題,是團隊前進的基本假設。
Inner-loop 性能項目是一個很好的例子。假定.NET 6應用程序都共享相同的基礎設施,例如使用相同的構建系統(tǒng)和庫。在存在技術差異的地方,如使用不同的運行時(CoreCLR 或 Mono)或代碼生成技術(AOT或JIT),我們將這些因素考慮在內并提供務實且適當?shù)捏w驗,并且偏向于幾乎不可察覺的體驗差異。EventPipe項目就是另一個類似的例子。
生產(chǎn)信心
我們將很快開始發(fā)布在生產(chǎn)中受支持的“上線”版本。我們目前正為此目標。我們的開發(fā)模型圍繞實現(xiàn)生產(chǎn)工作負載而進行,即使我們正在完成上述所有主題的工作。
生產(chǎn)信心始于 dotnet.microsoft.com 網(wǎng)站。從 Preview 1 開始,它已經(jīng)在 .NET 6 上運行了一半的站點負載。雖然規(guī)模不大,但對于我們的團隊來說,這是一個重要的站點,我們非常重視它。.NET 6一直像冠軍一樣為我們工作。
我們還與微軟使用.NET預覽版部署其生產(chǎn)應用程序團隊合作。他們這樣做是為了盡早使用新的 .NET 功能。這些團隊一直在尋找減少其云托管成本的機會,事實證明,部署新的.NET版本是最有效,最省力的方法之一。這些團隊為我們提供了早期反饋,可幫助我們確保新功能可用于全球生產(chǎn)。由于它們是我們的第一批生產(chǎn)用戶,因此它們也極大地影響最終特性的面貌。
所有這些對現(xiàn)實應用程序的早期測試都建立了我們對.NET 6將為運行您的應用程序做好準備的信心。
文章的其余部分專門介紹預覽版4中的新增功能。
工具:使用Visual Studio調試器和dotnetCLI進行熱重裝
Hot Reload是一種新體驗,使您可以在運行時對應用程序的源代碼進行編輯,而無需手動暫停應用程序或遇到斷點。Hot Reload通過減少重新啟動正在運行的應用程序所需的次數(shù)來提高開發(fā)人員的效率。
在此版本中,熱重加載可用于許多類型的應用程序,例如WPF,Windows窗體,WinUI,ASP.NET,控制臺應用程序以及在CoreCLR運行時之上運行的其他框架。我們也正在努力將該技術引入在Mono之上運行的WebAssembly,iOS和Android應用程序中,但這種技術仍將繼續(xù)開發(fā)(在以后的Preview中)。
若要開始測試此功能,請安裝Visual Studio 2019版本16.11 Preview 1,然后使用Visual Studio調試器(F5)啟動您的應用程序。應用程序運行后,您現(xiàn)在可以使用新選項進行代碼更改,并使用新的“應用代碼更改”按鈕應用代碼,如下所示。

也可以通過該dotnet watch工具進行熱重裝。預覽版4提供了很多修復可以改善這種體驗。
如果您想了解有關熱重載的更多信息,請閱讀.NET熱重載簡介。
System.Text.Json 對IAsyncEnumerable的支持
IAsyncEnumerable<T>是.NET Core 3.0和C#8中添加的一項重要功能。使用 IAsyncEnumerable<T> 實現(xiàn)了對 System.Text.Json的(反)序列化新的增強功能。
以下示例將流用作任何異步數(shù)據(jù)源的示例。數(shù)據(jù)源可以是本地計算機上的文件,也可以是數(shù)據(jù)庫查詢或Web服務API調用的結果。
流序列化
如下面的示例所示,System.Text.Json現(xiàn)在支持將IAsyncEnumerable<T>值序列化為JSON數(shù)組。
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
static async IAsyncEnumerable<int> PrintNumbers(int n)
{
for (int i = 0; i < n; i++) yield return i;
}
using Stream stream = Console.OpenStandardOutput();
var data = new { Data = PrintNumbers(3) };
await JsonSerializer.SerializeAsync(stream, data); // prints {"Data":[0,1,2]}
IAsyncEnumerable值僅支持使用異步序列化方法處理。嘗試使用同步方法進行序列化將導致NotSupportedException拋出異常。
流式反序列化
流式反序列化需要返回IAsyncEnumerable<T>的新API 。我們?yōu)榇颂砑恿?code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">JsonSerializer.DeserializeAsyncEnumerable方法,如下面的示例所示。
using System;
using System.IO;
using System.Text;
using System.Text.Json;
var stream = new MemoryStream(Encoding.UTF8.GetBytes("[0,1,2,3,4]"));
await foreach (int item in JsonSerializer.DeserializeAsyncEnumerable<int>(stream))
{
Console.WriteLine(item);
}
此示例將按需反序列化元素,并且在使用特別大的數(shù)據(jù)流時可能很有用。它僅支持從根級JSON數(shù)組讀取,盡管將來可以根據(jù)反饋放寬對它的讀取。
現(xiàn)有的 DeserializeAsync方法名義上支持IAsyncEnumerable<T>,但在其非流式方法簽名的范圍內,它必須以單個值返回最終結果。如以下示例所示。
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.Json;
var stream = new MemoryStream(Encoding.UTF8.GetBytes(@"{""Data"":[0,1,2,3,4]}"));
var result = await JsonSerializer.DeserializeAsync<MyPoco>(stream);
await foreach (int item in result.Data)
{
Console.WriteLine(item);
}
public class MyPoco
{
public IAsyncEnumerable<int> Data { get; set; }
}
在此示例中,反序列化程序將IAsyncEnumerable在返回反序列化對象之前將所有內容緩沖在內存中。這是因為解析器在返回結果之前需要讀取整個JSON。
System.Text.Json:可寫DOM功能
在寫JSON DOM功能增加了一個新的簡單和高性能的編程模型。這種新的API具有吸引力,因為它避免了序列化的復雜性和儀式以及DOM的傳統(tǒng)成本。System.Text.Json
這個新的API具有以下優(yōu)點:
在無法或不希望使用POCO類型的情況下,或者在JSON模式不固定且必須進行檢查的情況下,可以使用輕型替代序列化。 啟用對大樹子集的有效修改。例如,可以有效地導航到大JSON樹的子部分,并從該子部分讀取數(shù)組或反序列化POCO。LINQ也可以與此一起使用。 啟用使用C# dynamic關鍵字,該關鍵字允許使用松散類型的,更類似于腳本的模型。
我們正在尋找有關對支持dynamic的反饋。如果dynamic支持對您很重要,請給我們您的反饋。
更多詳細信息,請訪問dotnet / runtime#6098。
可寫的DOM API
可寫DOM公開了以下類型。
namespace System.Text.Json.Node
{
public abstract class JsonNode {...};
public sealed class JsonObject : JsonNode, IDictionary<string, JsonNode?> {...}
public sealed class JsonArray : JsonNode, IList<JsonNode?> {...};
public abstract class JsonValue : JsonNode {...};
}
示例代碼
下面的示例演示了新的編程模型。
// Parse a JSON object
JsonNode jNode = JsonNode.Parse("{"MyProperty":42}");
int value = (int)jNode["MyProperty"];
Debug.Assert(value == 42);
// or
value = jNode["MyProperty"].GetValue<int>();
Debug.Assert(value == 42);
// Parse a JSON array
jNode = JsonNode.Parse("[10,11,12]");
value = (int)jNode[1];
Debug.Assert(value == 11);
// or
value = jNode[1].GetValue<int>();
Debug.Assert(value == 11);
// Create a new JsonObject using object initializers and array params
var jObject = new JsonObject
{
["MyChildObject"] = new JsonObject
{
["MyProperty"] = "Hello",
["MyArray"] = new JsonArray(10, 11, 12)
}
};
// Obtain the JSON from the new JsonObject
string json = jObject.ToJsonString();
Console.WriteLine(json); // {"MyChildObject":{"MyProperty":"Hello","MyArray":[10,11,12]}}
// Indexers for property names and array elements are supported and can be chained
Debug.Assert(jObject["MyChildObject"]["MyArray"][1].GetValue<int>() == 11);
Microsoft.Extensions.Logging編譯時源代碼生成器
.NET 6引入了這種LoggerMessageAttribute類型。此屬性是命名空間Microsoft.Extensions.Logging的一部分,使用時,它會生成性能記錄API的源代碼。源代碼日志支持旨在為現(xiàn)代.NET應用程序提供高度可用和高性能的日志記錄解決方案。自動生成的源代碼依賴于ILogger接口和LoggerMessage.Define功能。
當LoggerMessageAttribute用于partial日志記錄方法時,將觸發(fā)源代碼生成器。觸發(fā)后,它既可以自動生成partial其修飾方法的實現(xiàn),也可以生成帶有有關正確用法提示的編譯時診斷。編譯時日志記錄解決方案在運行時通常比現(xiàn)有的日志記錄方法快得多。它通過消除裝箱,臨時分配和副本來最大程度地實現(xiàn)了這一目標。
與直接手動使用 LoggerMessage.Define API相比,有很多好處:
語法更短,更簡單:聲明性屬性的使用而不是進行模板式編碼。 指導開發(fā)人員的體驗:生成器會給出警告,以幫助開發(fā)人員做正確的事。 支持任意數(shù)量的日志記錄參數(shù)。 LoggerMessage.Define最多支持六個。支持動態(tài)日志級別。這單靠 LoggerMessage.Define是不可能的。
如果您想跟蹤改進和已知問題,請參閱dotnet / runtime#52549。
基本用法
要使用LoggerMessageAttribute,需要使用的類和方法partial。代碼生成器在編譯時觸發(fā),并生成該partial方法的實現(xiàn)。
public static partial class Log
{
[LoggerMessage(EventId = 0, Level = LogLevel.Critical, Message = "Could not open socket to `{hostName}`")]
public static partial void CouldNotOpenSocket(ILogger logger, string hostName);
}
在前面的示例中,日志記錄方法為static,并且日志級別在屬性定義中指定。在靜態(tài)上下文中使用屬性時,必須將ILogger實例作為參數(shù)。您也可以選擇在非靜態(tài)上下文中使用該屬性。有關更多示例和使用場景,請訪問有關編譯時日志記錄源生成器的文檔。
System.Linq增強
已添加新的System.LINQ API,這些API已由社區(qū)提出請求并做出了貢獻。
Enumerable 對Index和Range參數(shù)的支持
該方法現(xiàn)在從可枚舉的末尾接受索引,如下面的示例所示。Enumerable.ElementAt
Enumerable.Range(1, 10).ElementAt(^2); // returns 9
已添加一個接受參數(shù)的重載。它簡化了可枚舉序列的切片:Enumerable.Take``Range
source.Take(..3)代替source.Take(3)source.Take(3..)代替source.Skip(3)source.Take(2..7)代替source.Take(7).Skip(2)source.Take(^3..)代替source.TakeLast(3)source.Take(..^3)代替source.SkipLast(3)source.Take(^7..^3)代替。source.TakeLast(7).SkipLast(3)
感謝@dixin對此的貢獻。
TryGetNonEnumeratedCount
該TryGetNonEnumeratedCount方法嘗試在不強制枚舉的情況下獲取可枚舉的源的計數(shù)。如下面的示例所示,這種方法在需要在枚舉之前預先分配緩沖區(qū)的場景中很有用。
List<T> buffer = source.TryGetNonEnumeratedCount(out int count) ? new List<T>(capacity: count) : new List<T>();
foreach (T item in source)
{
buffer.Add(item);
}
TryGetNonEnumeratedCount 檢查源代碼是否實現(xiàn)ICollection/ICollection<T> 或利用Linq所采用的一些內部優(yōu)化。
DistinctBy/ UnionBy/ IntersectBy/ExceptBy
如下面的示例所示,已將新的變體添加到集合操作中,這些變體允許使用通過鍵選擇器函數(shù)指定相等性。
Enumerable.Range(1, 20).DistinctBy(x => x % 3); // {1, 2, 3}
var first = new (string Name, int Age)[] { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40) };
var second = new (string Name, int Age)[] { ("Claire", 30), ("Pat", 30), ("Drew", 33) };
first.UnionBy(second, person => person.Age); // { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40), ("Drew", 33) }
MaxBy/MinBy
MaxBy和MinBy方法允許使用鍵選擇器查找最大或最小元素,如以下示例所示。
var people = new (string Name, int Age)[] { ("Francis", 20), ("Lindsey", 30), ("Ashley", 40) };
people.MaxBy(person => person.Age); // ("Ashley", 40)
Chunk
Chunk 用于將可枚舉的源分塊為固定大小的切片,如以下示例所示。
IEnumerable<int[]> chunks = Enumerable.Range(0, 10).Chunk(size: 3); // { {0,1,2}, {3,4,5}, {6,7,8}, {9} }
感謝Robert Andersson對此實現(xiàn)的貢獻。
FirstOrDefault/ LastOrDefault/SingleOrDefault重載采取默認參數(shù)
現(xiàn)有FirstOrDefault/ LastOrDefault/SingleOrDefault方法如果源枚舉是空的返回default(T)。如您在以下示例中看到的那樣,添加了新的重載,該重載接受在這種情況下要返回的默認參數(shù)。
Enumerable.Empty<int>().SingleOrDefault(-1); // returns -1
感謝@ Foxtrek64對此實現(xiàn)的貢獻。
Zip 接受三個枚舉重載
該方法現(xiàn)在支持組合三個枚舉接口,你可以在下面的例子中看到。
var xs = Enumerable.Range(1, 10);
var ys = xs.Select(x => x.ToString());
var zs = xs.Select(x => x % 2 == 0);
foreach ((int x, string y, bool z) in Enumerable.Zip(xs,ys,zs))
{
}
感謝Huo Yaoyuan對此實現(xiàn)的貢獻。
大大提高了Windows上的FileStream性能
FileStream 已在.NET 6中重新編寫,以在Windows上具有更高的性能和可靠性。
在重新編寫項目已逐步在五個大PR:
引入FileStreamStrategy作為FileStream重寫的第一步 FileStream重寫第二部分 FileStream優(yōu)化 FileStream重寫:使用IValueTaskSource代替TaskCompletionSource FileStream重寫:在AsyncWindowsFileStreamStrategy中緩存ValueTaskSource
最終結果是FileStream在Windows上為異步IO創(chuàng)建時永不阻塞。這是一個重大改進。您可以在基準測試中觀察到這一點,我們將在稍后進行介紹。
配置
第一個PR支持FileStream在運行時選擇實現(xiàn)。此模式最明顯的好處是可以切換回舊的.NET 5實施,您可以在runtimeconfig.json中使用以下設置進行操作。
{
"configProperties": {
"System.IO.UseNet5CompatFileStream": true
}
}
我們計劃接下來添加一個io_uring策略,該策略利用在最近的lINUX內核中同名的功能。
性能基準
讓我們使用BenchmarkDotNet來衡量改進。
public class FileStreamPerf
{
private const int FileSize = 1_000_000; // 1 MB
private Memory<byte> _buffer = new byte[8_000]; // 8 kB
[GlobalSetup(Target = nameof(ReadAsync))]
public void SetupRead() => File.WriteAllBytes("file.txt", new byte[FileSize]);
[Benchmark]
public async ValueTask ReadAsync()
{
using FileStream fileStream = new FileStream("file.txt", FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 4096, useAsync: true);
while (await fileStream.ReadAsync(_buffer) > 0)
{
}
}
[Benchmark]
public async ValueTask WriteAsync()
{
using FileStream fileStream = new FileStream("file.txt", FileMode.Create, FileAccess.Write, FileShare.Read, bufferSize: 4096, useAsync: true);
for (int i = 0; i < FileSize / _buffer.Length; i++)
{
await fileStream.WriteAsync(_buffer);
}
}
[GlobalCleanup]
public void Cleanup() => File.Delete("file.txt");
}
```ini
BenchmarkDotNet=v0.13.0, OS=Windows 10.0.18363.1500 (1909/November2019Update/19H2)
Intel Xeon CPU E5-1650 v4 3.60GHz, 1 CPU, 12 logical and 6 physical cores
.NET SDK=6.0.100-preview.5.21267.9
[Host] : .NET 5.0.6 (5.0.621.22011), X64 RyuJIT
Job-OIMCTV : .NET 5.0.6 (5.0.621.22011), X64 RyuJIT
Job-CHFNUY : .NET 6.0.0 (6.0.21.26311), X64 RyuJIT
| Method | Runtime | Mean | Ratio | Allocated |
|---|---|---|---|---|
| ReadAsync | .NET 5.0 | 3.785毫秒 | 1.00 | 39 KB |
| ReadAsync | .NET 6.0 | 1.762毫秒 | 0.47 | 1 KB |
| WriteAsync | .NET 5.0 | 12.573毫秒 | 1.00 | 39 KB |
| WriteAsync | .NET 6.0 | 3.200毫秒 | 0.25 | 1 KB |
**環(huán)境:**具有啟用了BitLocker的SSD驅動器的Windows 10
結果:
現(xiàn)在,讀取1 MB文件的速度提高了2倍,而寫入速度則提高了4倍。 內存分配從39 KB減少到1 KB!這是97.5%的改善!
這些更改將為FileStreamWindows用戶提供顯著的改進。更多詳細信息,請訪問dotnet / core#6098。
增強的日期,時間和時區(qū)支持
迄今為止,與日期和時間相關的類型已進行了以下改進。
新的DateOnly和TimeOnly結構
添加了僅日期和時間結構,具有以下特征:
每個代表的一個 DateTime的一半,要么僅是日期部分,要么僅是時間部分。DateOnly是日期,周年紀念日和工作日的理想選擇。它與SQL Server的date類型一致。TimeOnly是定期會議,鬧鐘和每周工作時間的理想選擇。它與SQL Server的time類型一致。補充了現(xiàn)有的日期/時間類型( DateTime,DateTimeOffset,TimeSpan,TimeZoneInfo)。在 System命名空間中,與現(xiàn)有的相關類型一樣,在CoreLib中提供。
性能改進 DateTime.UtcNow
此改進具有以下好處:
修復了2.5倍的性能回歸,以獲取Windows上的系統(tǒng)時間。 利用5分鐘的Windows滑動緩存跳過第二個數(shù)據(jù),而不是每次調用都提取數(shù)據(jù)。
在所有平臺上均支持Windows和IANA時區(qū)
此改進具有以下優(yōu)點:
使用時的隱式轉換(https://github.com/dotnet/runtime/pull/49412) TimeZoneInfo.FindSystemTimeZoneById通過新的API顯式轉換上 TimeZoneInfo:TryConvertIanaIdToWindowsId,TryConvertWindowsIdToIanaId,和HasIanaId(https://github.com/dotnet/runtime/issues/49407)改進跨平臺的支持和使用不同時區(qū)類型的系統(tǒng)之間的互操作。 無需使用 TimeZoneConverter開源庫。該功能現(xiàn)已內置。
改進的時區(qū)顯示名稱
此改進具有以下好處:
從 TimeZoneInfo.GetSystemTimeZones中返回的列表中的顯示名稱中消除歧義。利用ICU / CLDR全球化數(shù)據(jù)。 僅限Unix。Windows仍使用注冊表數(shù)據(jù)。以后可能會更改。
其他
UTC時區(qū)的顯示名稱和標準名稱已硬編碼為英語,并且現(xiàn)在使用與其余時區(qū)數(shù)據(jù)相同的語言( CurrentUICulture在Unix上,在Windows為OS默認語言)。由于大小限制,WASM中的時區(qū)顯示名稱改用非本地化的IANA ID。 TimeZoneInfo.AdjustmentRule嵌套類將其BaseUtcOffsetDelta內部屬性公開,并獲取一個新的構造函數(shù)baseUtcOffsetDelta作為參數(shù)。(https://github.com/dotnet/runtime/issues/50256)TimeZoneInfo.AdjustmentRule還獲得了在Unix(https://github.com/dotnet/runtime/pull/49733)上加載時區(qū)的多項修復程序(https://github.com/dotnet/runtime/pull/50131)
CodeGen
RyuJIT編譯器進行了以下改進。
社區(qū)貢獻
在過去幾個月中,@ SingleAccretion一直在忙于以下改進。這是對.NET 6 Preview 3的補充。謝謝!
dotnet / runtime#50373 —如果樹是CSE候選者,不要棄用雙重否定 dotnet / runtime#50450 —處理通過幫助程序進行的強制轉換并在值編號中折疊溢出操作 dotnet / runtime#50702 —刪除了GS Cookies的必須初始化的要求 dotnet / runtime#50703 —不要混淆fgMorphBlocks中的fgDispBasicBlocks
動態(tài)PGO
為了支持動態(tài)PGO,進行了以下改進。
dotnet / runtime#51664 —更新JIT以使用從交叉基因處理的PGO數(shù)據(jù)中看到的新“ LikelyClass”記錄 dotnet / runtime#50213 —更好地容忍邊緣輪廓不一致 dotnet / runtime#50633 —修復了混合的PGO / nonPGO編譯 dotnet / runtime#50765 —修改fgExpandRunRarelyBlocks dotnet / runtime#51593 —修改內聯(lián)刻度計算
JIT循環(huán)優(yōu)化
對循環(huán)優(yōu)化進行了以下改進。
dotnet / runtime#50982 —概括循環(huán)反演 dotnet / runtime#51757 —不要在循環(huán)克隆期間重新計算preds列表
LSRA
對線性掃描寄存器分配(LRSA)進行了以下改進。
dotnet / runtime#51281 —改進LRSA統(tǒng)計信息以包括寄存器選擇啟發(fā)式信息
最佳化
dotnet / runtime#49930 —在值編號級別折疊空檢查const字符串 dotnet / runtime#50000 —對引用類型的初始化的靜態(tài)只讀字段進行折疊空檢查 dotnet / runtime#50112 —不要在潛在的BBJ_THROW候選對象中分配字符串文字 dotnet / runtime#50644 —為VectorX啟用CSE。 dotnet / runtime#50806 —如果后面沒有意外阻止,請放棄尾部調用 dotnet / runtime#50832 —更新 Vector<T>以支持nint和修改nuintdotnet / runtime#51409-概括圍繞分支空流程的優(yōu)化
.NET診斷:用于Mono的EventPipe和改進的EventPipe性能
EventPipe是.NET的跨平臺機制,用于輸出事件,性能數(shù)據(jù)和計數(shù)器。
從.NET 6開始,我們將實現(xiàn)從C ++移到了C。通過這一更改,Mono也將能夠使用EventPipe!這意味著CoreCLR和Mono將使用相同的事件基礎結構,包括.NET Diagnostics CLI工具!此更改還使CoreCLR的尺寸有所減小:
| LIB | 之后大小–之前大小 | 差異 |
|---|---|---|
| libcoreclr.so | 7037856 – 7049408 | -11552 |
我們還進行了一些更改,以提升高負載下的EventPipe吞吐量。在最初的幾個預覽中,我們進行了一系列更改,使吞吐量提高了.NET 5所能達到的2.06倍

使用 dotnet/diagnostics 中 EventPipeStress 框架收集的數(shù)據(jù)。應用程序以最快的速度寫入事件,持續(xù)60秒。記錄了成功和刪除事件的數(shù)量。
有關更多信息,請參見dotnet / runtime#45518。
IL Trimming
默認情況下啟用警告
修剪警告會告訴您修剪可能會刪除運行時使用的代碼的地方。以前默認情況下會禁用這些警告,因為這些警告非常嘈雜,這在很大程度上是由于.NET平臺未作為一流方案參與修剪。
我們已經(jīng)為.NET庫的大部分(運行時庫,而不是ASP.NET Core或Windows Desktop框架)添加了注解,以便它們產(chǎn)生準確的修剪警告。因此我們認為是時候默認啟用修整警告了。
您可以通過將設置<SuppressTrimAnalysisWarnings>為來禁用警告true。在早期版本中,您可以設置相同的屬性為false以查看修剪警告。
修剪警告為修剪過程帶來了可預測性,并增強了開發(fā)人員的控制能力。我們將繼續(xù)在以后的版本中注解更多的 .NET 庫,包括 ASP.NET Core。我們希望社區(qū)也將通過注解更多代碼以保護修剪安全,從而改善修剪生態(tài)系統(tǒng)。
更多信息:
.NET 6中的修剪警告 準備用于修剪的.NET庫
默認TrimMode=link
.NET 6中新的默認修剪模式為link。link TrimMode可以通過修剪不僅未使用的程序集還有不用的成員來顯著的修剪效果。
在.NET 5中,修剪默認情況下嘗試查找和刪除未引用的程序集。這樣比較安全,但收益有限。現(xiàn)在默認情況下,修剪警告處于打開狀態(tài),開發(fā)人員可以對修剪的結果充滿信心。
讓我們來看一下通過修整.NET SDK工具之一進行的修整改進。我將使用crossgen,Ready To Run 編譯器。Crossgen團隊能夠解決的問題僅需修剪一些警告即可進行修剪。
首先,讓我們看一下如何將Crossgen發(fā)布為一個自包含的應用程序,而無需進行修整。它是80 MB(包括.NET運行時和所有庫)。

然后,我們可以嘗試使用(現(xiàn)在是舊版的).NET 5默認修剪模式copyused。結果下降到55 MB。

新的.NET 6默認修剪模式link將自包含文件的大小進一步減小到36MB。

我們希望新的link修整模式能更好地滿足修整的期望:節(jié)省大量成本并獲得可預測的結果。
與NativeAOT共享的模型
我們還為Native AOT實驗實施了相同的修剪警告,這將以幾乎相同的方式改善Native AOT編譯體驗。
單文件發(fā)布
對單文件應用程序發(fā)布進行了以下改進。
靜態(tài)分析
.NET 5中添加了用于單文件發(fā)布的分析器,以警告Assembly.Location 和其他一些在單文件包中表現(xiàn)不同的API。
對于.NET 6 Preview 4,我們改進了分析以允許自定義警告。如果您有在單文件發(fā)布中不起作用的API,則可以使用屬性將其標記[RequiresAssemblyFiles],如果啟用了分析器,則會出現(xiàn)警告。添加該屬性還將使方法中與單個文件相關的所有警告均消除,因此您可以使用該警告將警告向上傳播到公共API。
PublishSingleFile設置為true時,會為exe項目自動啟用分析器,但也可以通過設置EnableSingleFileAnalysis為true來為任何項目啟用分析器。如果要將庫嵌入單個文件包中,這可能會有所幫助。
壓縮
現(xiàn)在單文件包支持壓縮,這可以通過設置屬性EnableCompressionInSingleFile到true來啟用。在運行時,根據(jù)需要將文件解壓縮到內存中。在某些情況下,壓縮可以節(jié)省大量空間。
讓我們看一下NuGet Package Explorer一起使用的壓縮和不壓縮的單個文件發(fā)布。
不壓縮:172 MB

壓縮后:71.6 MB

壓縮會大大增加應用程序的啟動時間,尤其是在Unix平臺上(因為它們具有無法與壓縮一起使用的無副本快速啟動路徑)。啟用壓縮后,應該測試您的應用程序,以查看是否可以接受額外的啟動成本。
PublishReadyToRun 現(xiàn)在默認使用crossgen2
默認情況下,發(fā)布 ReadyToRun 時會啟用 Crossgen2。它還可選地支持生成組合配置。
公開了以下設置,使您可以配置發(fā)布并準備運行代碼。下面的設置被設置為其默認值。
<PublishReadyToRun>false</PublishReadyToRun>
<!-- set to true to enable publishing with ready to run native code -->
<PublishReadyToRunUseCrossgen2>true</PublishReadyToRunUseCrossgen2>
<!-- set to false to use crossgen like in 5.0 -->
<PublishReadyToRunComposite>false</PublishReadyToRunComposite>
<!-- set to true to generate a composite R2R image -->
CLI安裝.NET 6 SDK可選工作負載
.NET 6將介紹SDK工作負載的概念,可以在.NET SDK之上安裝之后,以啟用各種方案。預覽4中提供的新工作負載是.NET MAUI和Blazor WebAssembly AOT工作負載。
對于.NET MAUI工作負載,我們仍建議對預覽4使用maui-check工具,因為它包含Visual Studio中尚不可用的其他組件或作為.NET SDK工作負載。要嘗試試用.NET SDK的經(jīng)驗(以iOS為例),請運行dotnet workload install microsoft-ios-sdk-full。安裝后,您可以運行,然后dotnet new ios創(chuàng)建和dotnet build構建您的項目。
對于Blazor WebAssembly AOT,請按照ASP.NET博客提供的安裝說明進行操作。
預覽4包括適用于iOS,Android,tvOS,MacOS和MacCatalyst的.NET MAUI工作負載。
請注意,dotnet workload install將工作負載從NuGet.org復制到您的SDK安裝中,因此,如果SDK安裝位置受到保護(意味著在admin / root位置),則需要以高權限/ sudo運行。
內置SDK版本檢查
為了更容易跟蹤何時有新版本的SDK和運行時,我們向.NET 6 SDK添加了新命令:dotnet sdk check
這將告訴您在每個功能范圍內什么是.NET SDK和.NET Runtime的最新可用版本。

CLI模板(dotnet new)
預覽4引入了模板的新搜索功能。將在NuGet.org中搜索匹配的模板。在即將到來的預覽期間,用于此搜索的數(shù)據(jù)將更頻繁地更新。dotnet new --search
CLI中安裝的模板可用于CLI和Visual Studio。解決了一個較早的問題,即在安裝新版本的SDK時,用戶安裝的模板丟失了,但是,需要重新安裝在.NET 6 Preview 4之前安裝的模板。
模板安裝的其他改進包括支持--interactive開關以支持私有NuGet提要的授權憑據(jù)。
安裝CLI模板后,您可以通過--update-check和--update-apply檢查更新是否可用。現(xiàn)在,這將更快地反映模板更新,支持您已定義的NuGet提要,并支持--interactive授權憑證。
在預覽4和即將發(fā)布的預覽中,dotnet new命令的輸出將被清除以專注于您最需要的信息。例如,dotnet new --install <package> 列表僅列出剛安裝的模板,而不列出所有模板。
為了支持對dotnet new的這些更改和即將進行的更改,我們正在對模板引擎API進行重大更改,這可能會影響托管模板引擎的任何人。這些更改將顯示在Preview 4和Preview 5中。如果您托管模板引擎,請通過https://github.com/dotnet/templating與我們聯(lián)系,以便我們與您合作以避免或最大程度地減少干擾。
支持
.NET 6將在2021年11月發(fā)布,并且將作為長期支持(LTS)版本獲得三年的支持。該支持平臺已顯著擴大。
新增內容包括:
安卓。 iOS。 Mac和Mac Catalyst,用于x64和Apple Silicon(又稱“ M1”)。 Windows Arm64(特別是Windows桌面)。
.NET 6 Debian容器映像基于當前正在測試中的Debian 11(“ bullseye”)。
Closing
現(xiàn)在,我們可以很好地進入.NET 6版本了。雖然11月的最終版本似乎還有很長的路要走,但我們正接近完成功能開發(fā)。現(xiàn)在是獲得反饋的好時機,因為現(xiàn)已確定了新功能,并且我們仍處于積極的開發(fā)階段,因此可以隨時根據(jù)反饋采取行動。
說到11月,請在11月9日至11日預訂一些時間觀看.NET Conf 2021,肯定會令人興奮和而且會很有趣。我們將在11月9日發(fā)布最終的.NET 6構建,并且將有一篇甚至更長的博客文章。
還在尋找更多閱讀內容嗎?您可以查看我們新的對話系列。有關.NET 6的新功能,有很多詳細的見解。
我們希望您享受嘗試 Preview 4。


被網(wǎng)易云刷屏的人格顏色測試,我來總結下……爆火,點擊查看>>>

【限時刪】劉*55頁ppt大瓜,比項*醒的還要精彩!
