首頁>技術>

.NET 6 預覽版 7 Released

Richard 2021 年 8 月 10 日

我們很高興釋出 .NET 6 Preview 7。這是我們進入(兩個)釋出候選 (RC) 期之前的最後一次預覽版本。在我們放慢釋出速度之前,團隊經常加班夜戰來保證最後一組功能。在這個版本中,您將看到對各種功能的最後一點潤色,以及一次性推出的大型功能。從這一點來看,該團隊將專注於將所有功能實現統一(高)質量,以便 .NET 6 為您的生產工作負載做好準備。

關於生產環境工作負載的話題,值得提醒大家的是,.NET 網站 和 Bing.com 自預覽版 1 以來一直在 .NET 6 上執行。我們正在與各個團隊(Microsoft 和其他團隊)聯絡將.NET 6 RC 用於生產。如果您對此感興趣並希望獲得有關如何處理該問題的指導,請聯絡 [email protected],我們總是樂於與早期採用者交流。

您可以下載適用於 Linux、macOS 和 Windows 的.NET 6 Preview 7。

安裝程式和二進位制檔案容器映象Linux 軟體包發行說明API差異已知問題GitHub Issue 追蹤

有關客戶端和 Web 應用程式方案新增功能的更多詳細資訊,請參閱.NET MAUI和ASP.NET Core。

.NET 6 Preview 7 已經過測試,並且受Visual Studio 2022 Preview 3 支援。Visual Studio 2022 使您能夠利用為 .NET 6 開發的 Visual Studio 工具,例如在 .NET MAUI 中進行開發、C# 應用程式的熱過載、WebForms 的新 Web 實時預覽以及 IDE 體驗中的其他效能改進。Visual Studio Code也支援 .NET 6 。Visual Studio Code的 C# 擴充套件的最新版本已針對 .NET 6 Preview 7 進行了更新,並且包括對 C# 10 的支援。

.NET SDK:現代化的 C# 專案模板

我們更新了 .NET SDK 模板以使用最新的 C# 語言功能和模式。我們已經有一段時間沒有在新的語言功能方面重新審視模板了。是時候這樣做了,我們將確保模板在未來使用新的和現代的功能。

新模板中使用了以下語言功能:

頂級語句非同步 Main 方法全域性 using 指令(透過 SDK 驅動的預設值)檔案範圍的名稱空間目標型別的新表示式可空引用型別

您可能想知道為什麼我們透過模板啟用某些功能,而不是在專案面向 .NET 6 時預設啟用它們。您需要做一些工作來將應用程序升級到新版本的 .NET, 作為用於權衡改進平臺的預設行為,這使我們可以改進產品,而不會隨著時間的推移使專案檔案複雜化。但是,該模型的某些功能可能會具有破壞性,例如可為空的引用型別。我們不想將這些功能與升級體驗聯絡起來,但希望將選擇權留給您,無論何時何地。模板是一個風險低得多的樞軸點,我們可以在那裡為新程式碼透過專案模板啟用這些功能,設定新的“良好預設模型”,而幾乎沒有下游後果。

控制檯模板

Console模板演示了最大的變化。憑藉頂級語句和全域性 using 指令,它現在(有效的程式碼)是隻有一行的。

// See https://aka.ms/new-console-template for more informationConsole.WriteLine("Hello, World!");

同一模板的 .NET 5 版本包括幾行熟悉的樣式,新的模板只需要一行程式碼就可以提供以前實際程式碼所需的結構。

using System;namespace Company.ConsoleApplication1{    class Program    {        static void Main(string[] args)        {            Console.WriteLine("Hello, World!");        }    }}

console模板的專案檔案也已更改,以啟用可空引用型別功能,如下例所示

<Project Sdk="Microsoft.NET.Sdk">  <PropertyGroup>    <OutputType>Exe</OutputType>    <TargetFramework>net6.0</TargetFramework>    <Nullable>enable</Nullable>  </PropertyGroup></Project>

其他模板也支援可空性、隱式全域性使用和檔案範圍的名稱空間,包括 ASP.NET Core 和類庫。

ASP.NET Web 模板

web模板也同樣在使用相同的功能來減少程式碼行

var builder = WebApplication.CreateBuilder(args);var app = builder.Build();if (app.Environment.IsDevelopment()){    app.UseDeveloperExceptionPage();}app.MapGet("/", () => "Hello World!");app.Run();

ASP.NET MVC 模板

mvc模板在結構上相似。在本例中,我們已將Program.cs和Startup.cs合併到一個檔案 ( Program.cs) 中,從而進一步簡化。

var builder = WebApplication.CreateBuilder(args);// Add services to the container.builder.Services.AddControllersWithViews();var app = builder.Build();// Configure the HTTP request pipeline.if (app.Environment.IsDevelopment()){    app.UseDeveloperExceptionPage();}else{    app.UseExceptionHandler("/Home/Error");    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.    app.UseHsts();}app.UseHttpsRedirection();app.UseStaticFiles();app.UseRouting();app.UseAuthorization();app.MapControllerRoute(    name: "default",    pattern: "{controller=Home}/{action=Index}/{id?}");app.Run();

模板相容性

有關使用新模板的相容性問題,請參閱以下文件。

早期 .NET 版本不支援模板中的 C# 程式碼隱式名稱空間匯入

庫:用於可空性資訊的反射 API

可空引用型別是編寫可靠程式碼的重要特性。它非常適合編寫程式碼,但不適用於(直到現在)反射檢查它。新的反射 API使您能夠確定給定方法的引數和返回值的可空性性質。例如,這些新的 API 對基於反射的工具和序列化程式至關重要。

對於上下文,我們在 .NET 5 中向 .NET 庫添加了可為空的註釋(並在 .NET 6 中完成),並且正在對本版本的ASP.NET Core做同樣的事情。我們還看到開發人員為他們的專案採用可空引用型別。

可空性資訊使用自定義屬性儲存在元資料中。原則上,任何人都可以讀取自定義屬性,但是,這並不理想,因為使用編碼是很重要的。

以下示例演示了將新 API 用於幾個不同的場景。

獲取頂級可空性資訊

假設您正在實現一個序列化程式。使用這些新的 API,序列化程式可以檢查給定的屬性是否可以設定為null:

private NullabilityInfoContext _nullabilityContext = new NullabilityInfoContext();private void DeserializePropertyValue(PropertyInfo p, object instance, object? value){    if (value is null)    {        var nullabilityInfo = _nullabilityContext.Create(p);        if (nullabilityInfo.WriteState is not NullabilityState.Nullable)        {            throw new MySerializerException($"Property '{p.GetType().Name}.{p.Name}'' cannot be set to null.");        }    }    p.SetValue(instance, value);}

獲取巢狀的可空性資訊

可空性對可以(正式地)儲存其他物件(如陣列和元組)的物件進行了特殊處理。例如,您可以指定陣列物件(作為變數,或作為型別成員簽名的一部分)必須為非空,但元素可以為空,反之亦然。使用新的反射 API 可以檢查這種額外級別的特異性,如以下示例所示。

class Data{    public string?[] ArrayField;    public (string?, object) TupleField;}private void Print(){    Type type = typeof(Data);    FieldInfo arrayField = type.GetField("ArrayField");    FieldInfo tupleField = type.GetField("TupleField");    NullabilityInfoContext context = new ();    NullabilityInfo arrayInfo = context.Create(arrayField);    Console.WriteLine(arrayInfo.ReadState);        // NotNull    Console.WriteLine(arrayInfo.Element.State);    // Nullable    NullabilityInfo tupleInfo = context.Create(tupleField);    Console.WriteLine(tupleInfo.ReadState);                      // NotNull    Console.WriteLine(tupleInfo.GenericTypeArguments [0].State); // Nullable    Console.WriteLine(tupleInfo.GenericTypeArguments [1].State); // NotNull}

庫:ZipFile 遵循 Unix 檔案許可權

System.IO.Compression.ZipFile 型別現在在類Unix作業系統讀取 zip 檔案時,在建立和設定檔案許可權期間會捕獲 Unix 檔案許可權,此更改允許透過 zip 檔案來回傳送可執行檔案,這意味著您不再需要在解壓縮 zip 存檔後修改檔案許可權以使檔案可執行。這也遵循了讀/寫許可權,以及user/group/other 許可權。

如果 zip 文件不包含檔案許可權(因為它是在 Windows 上建立的,或者使用未捕獲許可權的工具,如 .NET 的早期版本),則提取的檔案將獲得預設檔案許可權,就像任何其他檔案一樣新建立的檔案。

Unix 檔案許可權也適用於其他 zip 存檔工具,包括:

Info-ZIP7-Zip

.NET 7 早期功能預覽:通用數學

對於 .NET 6,我們已經構建了將 API 標記為“預覽中”的功能。這種新方法將使我們能夠跨多個主要版本提供和使用預覽功能。為了使用預覽 API,專案需要明確選擇使用預覽功能。如果您在未明確選擇的情況下使用預覽功能,您將看到帶有可操作訊息的構建錯誤,從 .NET 6 RC1 開始。在以後的版本中,預覽功能可能會以破壞性的方式發生變化。這就是讓他們加入的原因。

我們在 .NET 6 中預覽的其中一項功能是靜態抽象介面成員。這些允許您在介面中定義靜態抽象方法(包括運算子)。例如,現在可以實現代數泛型方法。對於某些人來說,此功能將是我們今年提供的絕對出色的改進,這可能會使Span<T> 之後的最重要的新的型別系統功能。

以下示例使用了一個 IEnumerable<T> 物件並且由於 T被限制為INumber<T>, 可能是INumber<int>,因此能夠對所有值求和

public static T Sum<T>(IEnumerable<T> values)    where T : INumber<T>{    T result = T.Zero;    foreach (var value in values)    {        result += value;    }    return result;}

這是有效的,因為 INumber<T> 定義了介面實現者必須滿足的各種(靜態)運算子過載。IAdditionOperators 也許是最簡單的新介面來理解,這本身是從INumber 繼承的。

這裡提到的所有功能都是 .NET 6 的預覽功能,不支援在生產中使用。我們將不勝感激您使用它們的反饋。我們打算在 .NET 7 中繼續發展和改進通用數學功能以及支援它們的執行時和 C# 功能。我們希望對當前體驗進行重大更改,這也是新 API 被標記為”在預覽中”的部分原因。

庫:NativeMemory API

我們增加了新的本機記憶體分配的API透過System.Runtime.InteropServices.NativeMemory暴露。這些 API 代表了malloc、free、realloc和calloc C API 的等價物,還包括用於進行對齊分配的 API。

您可能想知道如何考慮這些 API。首先,它們是用於底層程式碼和演算法的低階 API。應用程式開發人員很少會使用這些。考慮這些 API 的另一種方式類似於平臺內在API,它們是用於晶片指令的低階 .NET API。這些 API 很相似,但為與記憶體相關的操作公開了低階 API。

庫:System.Text.Json 序列化通知

System.Text.Json 序列化程式現在將通知作為(反)序列化操作的一部分公開。它們對於預設值和驗證很有用。要使用它們,實現一個或多個介面IJsonOnDeserialized,IJsonOnDeserializing,IJsonOnSerialized或IJsonOnSerializing在 System.Text.Json.Serialization 名稱空間下。

這是一個在JsonSerializer.Serialize() 和 JsonSerializer.Deserialize() 兩者期間都進行驗證並確保屬性FirstName不是null的示例。

  public class Person : IJsonOnDeserialized, IJsonOnSerializing  {      public string FirstName{ get; set; }      void IJsonOnDeserialized.OnDeserialized() => Validate(); // Call after deserialization      void IJsonOnSerializing.OnSerializing() => Validate(); // Call before serialization      private void Validate()      {          if (FirstName is null)          {              throw new InvalidOperationException("The 'FirstName' property cannot be 'null'.");          }      }  }

在以前,您需要實現自定義轉換器才能實現此功能。

庫:System.Text.Json 序列化屬性排序

我們還添加了控制屬性序列化順序的功能,使用 System.Text.Json.Serialization.JsonPropertyOrderAttribute. 一個整數指定順序。較小的整數首先被序列化;沒有屬性的屬性的預設排序值為 0。

這是一個指定 JSON 應按順序序列化的示例:Id, City, FirstName, LastName

public class Person{    public string City { get; set; } // No order defined (has the default ordering value of 0)    [JsonPropertyOrder(1)] // Serialize after other properties that have default ordering    public string FirstName { get; set; }    [JsonPropertyOrder(2)] // Serialize after FirstName    public string LastName { get; set; }    [JsonPropertyOrder(-1)] // Serialize before other properties that have default ordering    public int Id { get; set; }}

以前,序列化順序是由反射順序決定的,它既不是確定性的,也不是導致特定的所需順序。

庫:使用 System.Text.Json.Utf8JsonWriter“編寫原始”JSON

在使用 Utf8JsonWriter編寫 JSON 有效負載時,有時您需要整合“原始”JSON。

例如:

我有一個有意在網路上寫出的位元組序列,並且我知道我在做什麼(如下例所示)。我有一個 blob,我認為它代表 JSON 內容並且我想將其封裝起來,我需要確保信封及其內部內容保持格式正確
JsonWriterOptions writerOptions = new() { WriteIndented = true, };using MemoryStream ms = new();using UtfJsonWriter writer = new(ms, writerOptions);writer.WriteStartObject();writer.WriteString("dataType", "CalculationResults");writer.WriteStartArray("data");foreach (CalculationResult result in results){    writer.WriteStartObject();    writer.WriteString("measurement", result.Measurement);    writer.WritePropertyName("value");    // Write raw JSON numeric value using FormatNumberValue (not defined in the example)    byte[] formattedValue = FormatNumberValue(result.Value);    writer.WriteRawValue(formattedValue, skipValidation: true);    writer.WriteEndObject();}writer.WriteEndArray();writer.WriteEndObject();

下面是對上面程式碼——特別是FormatNumberValue——正在做什麼的描述。為了效能,System.Text.Json當數字為整數時省略小數點/值,例如1.0. 基本原理是寫入更少的位元組有利於效能。在某些情況下,保留十進位制值可能很重要,因為消費者將沒有小數的數字視為整數,否則視為雙精度數。這種新的“原始值”模型使您可以隨時隨地進行控制。

庫:同步流過載JsonSerializer

我們添加了新的同步 API,JsonSerializer用於在流中序列化和反序列化 JSON 資料。您可以在以下示例中看到這一點。

using MemoryStream ms = GetMyStream();MyPoco poco = JsonSerializer.Deserialize<MyPoco>(ms);

這些新的同步 API 包括透過接受JsonTypeInfo<T>或JsonSerializerContext例項與新的System.Text.Json 源生成器相容和可用的過載。

庫:刪除了System.Text.Json.Nodes.JsonNode 對dynamic的支援

JsonSerializer 中對 C# dynamic 型別的支援已被刪除。我們dynamic在預覽版 4 中添加了支援,但後來決定是一個糟糕的設計選擇,包括使其成為JsonNode型別的必需依賴項。

此更改被認為是從 .NET 6 一個預覽到另一個預覽的重大更改,但不是從 .NET 5 到 6。

庫:System.Diagnostics Propagators

在過去幾年中,我們一直在改進對OpenTelemetry 的支援。實現強大支援的關鍵方面之一是確保需要參與遙測生產的所有元件以正確的格式生成網路標頭。這真的很難做到,尤其是隨著 OpenTelemetry 規範的變化。OpenTelemetry 定義了傳播概念來幫助解決這種情況。我們正在採用傳播來啟用標頭自定義的通用模型。

更廣泛概念的背景:

OpenTelemetry規範——分散式跟蹤資料結構的記憶體表示。OpenTelemetry Span — 用於跟蹤的構建塊,由.NET 中的System.Diagnostics.Activity表示。W3C TraceContext — 關於如何透過眾所周知的 HTTP 標頭傳播這些分散式跟蹤資料結構的規範。

以下程式碼演示了使用傳播的一般方法。

DistributedContextPropagator propagator = DistributedContextPropagator.Current;propagator.Inject(activity, carrier, (object theCarrier, string fieldName, string value) =>{   // Extract the context from the activity then inject it to the carrier.});

您還可以選擇使用不同的傳播器。

// Set the current propagation behavior to not transmit any distributed context information in outbound network messages.DistributedContextPropagator.Current = DistributedContextPropagator.CreateNoOutputPropagator();

該DistributedContextPropagator抽象類確定是否和如何分配的上下文資訊進行編碼和解碼,因為它穿過網路。編碼可以透過任何支援鍵值字串對的網路協議傳輸。DistributedContextPropagator將值注入到載體中並從載體中提取值作為鍵/值字串對。透過新增對傳播器的支援,我們啟用了兩件事:

您不再需要使用W3C TraceContext標頭。您可以編寫自定義傳播器(即,使用您自己的標頭名稱,包括根本不傳送它們),而無需庫 HttpClient、ASP.NET Core 具有此自定義格式的先驗知識如果您使用自定義傳輸(例如,訊息佇列)實現庫,則現在可以支援各種有線格式,只要您支援傳送和接收文字對映(例如)Dictionary<string, string>

大多數應用程式程式碼不需要直接使用此功能,但是,如果您使用 OpenTelemetry,您很可能會在呼叫堆疊中看到它。如果關心跟蹤和因果關係,一些庫程式碼將可能參與此模型。

庫:加密操作的簡化呼叫模式

.NET 加密和解密例程是圍繞流設計的,沒有定義有效負載何時已經在記憶體中的真正概念。新的 Encrypt- 和 Decrypt- 方法SymmetricAlgorithm加速了記憶體中已經存在的情況,旨在為呼叫者和程式碼審查者提供清晰的資訊。此外,它們支援從跨度讀取和向跨度寫入。

新的簡化方法提供了一種使用加密 API 的直接方法:

private static byte[] Decrypt(byte[] key, byte[] iv, byte[] ciphertext){    using (Aes aes = Aes.Create())    {        aes.Key = key;        return aes.DecryptCbc(ciphertext, iv);    }}

使用新的 Encrypt- 和 Decrypt- 方法,僅使用來自 SymmetricAlgorithm 例項的 key 屬性。新的 DecryptCbc 方法支援選擇填充演算法,但 PKCS#7 經常與 CBC 一起使用,因此它是預設引數。如果您喜歡清晰模式,只需指定它:

private static byte[] Decrypt(byte[] key, byte[] iv, byte[] ciphertext){    using (Aes aes = Aes.Create())    {        aes.Key = key;        return aes.DecryptCbc(ciphertext, iv, PaddingMode.PKCS7);    }}

您可以看到現有模式(使用 .NET 5)需要更多的管道才能獲得相同的結果。

private static byte[] Decrypt(byte[] key, byte[] iv, byte[] ciphertext){    using (Aes aes = Aes.Create())    {        aes.Key = key;        aes.IV = iv;        // These are the defaults, but let's set them anyways.        aes.Padding = PaddingMode.PKCS7;        aes.Mode = CipherMode.CBC;        using (MemoryStream destination = new MemoryStream())        using (ICryptoTransform transform = aes.CreateDecryptor())        using (CryptoStream cryptoStream = new CryptoStream(destination, transform, CryptoStreamMode.Write))        {            cryptoStream.Write(ciphertext, 0, ciphertext.Length);            cryptoStream.FlushFinalBlock();            return destination.ToArray();        }    }}

庫:全球化不變模式下的完整案例對映支援

全球化不變模式使您能夠消除應用程式對全球化資料和行為的依賴,以換取較小的應用程式(主要在 Linux 上)。我們改進了全球化不變模式以支援完整 Unicode 字符集的大小寫對映。運營之前,該模式只支援ASCII字元範圍比如 String.ToUpper,String.ToLower和字串比較,並與搜尋IGNORECASE選項。

基於 Alpine 的 .NET 容器映象是我們預設啟用全球化環境模式的唯一環境。

執行時:W^X支援所有平臺和架構

執行時現在有一種模式,在這種模式下,它不會同時建立或使用任何可寫和可執行的記憶體頁。所有可執行記憶體都對映為只讀。此功能已在 macOS(適用於 Apple Silicon)上啟用。在 Apple Silicon 機器上,同時可寫和可執行的記憶體對映是被禁止的。

此功能現已在所有其他平臺上啟用和支援,作為可選體驗。在這些平臺上,可執行程式碼的生成/修改是透過單獨的讀寫記憶體對映完成的。這對於 JIT 程式碼和執行時生成的幫助程式都是正確的。這些對映是在與可執行程式碼地址不同的虛擬記憶體地址處建立的,並且僅在執行寫入時存在很短的時間。例如,JIT 現在將程式碼生成到暫存緩衝區中,在整個方法被 JIT 之後,使用單個記憶體複製函式呼叫將程式碼複製到可執行記憶體中。並且可寫對映生命週期僅跨越記憶體複製的時間。

可以透過將環境變數設定DOTNET_EnableWriteXorExecute為1. 此功能在 .NET 6 中是可選的,因為它具有啟動迴歸(Apple Silicon 除外)。在我們的 ASP.Net 基準測試中,當使用 Ready To Run (R2R) 編譯時,迴歸約為 10%。但是,在啟用和不啟用該功能的情況下,測量的穩態效能相同。對於啟動效能不重要的應用程式,我們建議啟用此功能以提高其提供的安全性。我們打算在 .NET 7 中解決效能迴歸問題,並在那時預設啟用該功能。

執行時:CodeGen 變更日誌

在預覽版 7 中的程式碼生成中進行了以下更改。

社群 PR

以下 PR 均來自@SingleAccrtion:

最佳化 32 位目標 runtime#53040CAST(int <- long)消除對小型別的鏈式轉換 runtime#52561從除法變形中刪除一些不需要的程式碼 runtime#53464修復長 muls 變形中的 CQ 迴歸和正確性錯誤 runtime#53566最佳化窄儲存不要消除 FP 型別的強制轉換 runtime#53667移動“不要零擴充套件 setcc”最佳化以降低 runtime#53778禁用實現定義的強制轉換的摺疊 runtime#53782為 VNF_MapStore 和 VNF_MapSelect 新增 args 描述 runtime#54108匯入cgt.un(op, 0)為NE(op, 0) runtime#54539使用本地斷言道具在返回省略強制轉換 runtime#55632

動態 PGO

以下 PR 支援動態 PGO 專案。

[JIT] 改進 inliner:新啟發式,依賴 PGO 資料 runtime#52708內聯:擴充套件配置呼叫站點的 IL 限制,允許內聯交換機。runtime#55478JIT:靜態類推導失敗時啟用GDV。runtime#55660

LSRA

以下 PR 支援LRSA 專案。

在定義時溢位單定義變數以避免進一步溢位 runtime#54345在 minopts 中將 vars 標記為 do not enreg。runtime#54998

迴圈最佳化

以下 PR 改進了迴圈最佳化。

改進迴圈克隆,除錯改進 runtime#55299支援使用結構索引表示式的陣列克隆迴圈 runtime#55612將 RyuJIT 最佳化的最大迴圈從 16 增加到 64。runtime#55614

結構

以下 PR 改進了結構處理。

在 win x64 上註冊結構體。runtime#55045Enreg Windows x86 struct。runtime#55535在所有平臺上預設啟用 StructEnreg。runtime#55558改進 TryTransformStoreObjAsStoreInd 最佳化。runtime#55727

最佳化

以下 PR 提供了一般最佳化。

布林邏輯中的“==0”最佳化 #13573 runtime#49548尾呼叫時允許隱式擴充套件runtime#54864

貢獻者展示

我們即將——正如多次提到的那樣——釋出到最後。我們想花點時間展示一些做出重大貢獻的社群貢獻者。有很多人做出了重大貢獻。以下人員是從團隊中的一些人中被提名參加這次展示的。如果人們喜歡,我們可以繼續這個展示部分。

文字是用貢獻者自己的話寫的。

Andrii Kurdiumov (@kant2002)

我是 Andrii Kurdiumov,住在哈薩克的阿拉木圖。透過貿易,我致力於在企業中構建新產品。

我決定為 .NET 做出貢獻,因為我看到了利用新的 MS 技術進入新市場的機會。Blazor WebAssembly 和 .NET on Raspberry 執行良好,但我擔心這些技術會在極端或不尋常的要求下崩潰。所以我決定花一點時間來看看 NativeAOT 是否可以幫助我。到目前為止,我的貢獻主要集中在 NativeAOT 專案上,甚至是 WinForms 專案。有一段時間我計劃遵循這個方向。

這些就是我開始貢獻的原因。我繼續貢獻的原因如下:我不斷感受到 .NET 工作人員的支援,我知道他們在軟體開發的廣闊領域擁有豐富的經驗。圍繞 .NET 工作的人們非常關心高質量標準,這立即為周圍的任何人定下了基調。我個人喜歡這種環境。

SingleAccretion

我是一個有抱負的年輕程式設計師,出人意料地來自俄羅斯。作為一個編寫程式碼的人,我從 .NET 開始,逐漸從技術棧的較高層轉到較低層,最終在編譯器上工作,就在虛擬機器的空白邊緣:), . 這是一種相當迷人的活動,瞭解與 RyuJit 一樣複雜和古老的系統,但這也是它獨特的吸引力,我想,至少對於像我這樣好奇的人來說。

然而,這不是我為 .NET 做出貢獻的原因,畢竟我可以開始自己的分支。我認為可以公平地說,在這幾個月裡涉足瞭如此多的 GH 執行緒,在任何地方都無法看到人們對我們領域的問題有如此深刻和豐富的理解。成為這個社群的一員,並且能夠對其中的問題進行推理,這是我真正珍惜的東西。

結語

我們正處於發行版的新時期,我們認為新功能和改進已經完成。幹得漂亮,團隊。這是另一季 .NET 預覽的結束。

我們繼續希望得到並依賴您的反饋。我們將把 .NET 6 的其餘部分集中在迴歸(功能和效能)和新功能中發現的錯誤上。在大多數情況下,功能改進需要等待 .NET 7。請分享您的任何和所有反饋,我們很樂意對其進行分類。

感謝所有為 .NET 6 成為另一個偉大版本做出貢獻的人。

感謝您成為 .NET 開發人員。

10
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • shell 統計cpu、記憶體使用率