.NET 9'daki yenilikler

.NET 9'daki yeni özellikler hakkında bilgi edinin ve diğer belgelerin bağlantılarını bulun.

.NET 8'in ardılı olan .NET 9, buluta özel uygulamalara ve performansa özel bir odaklanmıştır. Standart vadeli destek (STS) sürümü olarak 18 ay boyunca desteklenecektir. .NET 9'ı buradan indirebilirsiniz.

.NET 9'da yeni olan mühendislik ekibi GitHub Tartışmaları'nda .NET 9 önizleme güncelleştirmelerini gönderir. Burası soru sormak ve sürüm hakkında geri bildirim sağlamak için harika bir yerdir.

Bu makale .NET 9 Önizleme 2 için güncelleştirildi. Aşağıdaki bölümlerde .NET 9'daki çekirdek .NET kitaplıklarına yönelik güncelleştirmeler açıklanmaktadır.

.NET çalışma zamanı

Serileştirme

içinde System.Text.Json.NET 9'da JSON'ı seri hale getirmek için yeni seçenekler ve web varsayılanlarını kullanarak serileştirmeyi kolaylaştıran yeni bir tekil vardır.

Girinti seçenekleri

JsonSerializerOptions , yazılmış JSON'un girinti karakterini ve girinti boyutunu özelleştirmenize olanak sağlayan yeni özellikler içerir.

var options = new JsonSerializerOptions
{
    WriteIndented = true,
    IndentCharacter = '\t',
    IndentSize = 2,
};

string json = JsonSerializer.Serialize(
    new { Value = 1 },
    options
    );
Console.WriteLine(json);
//{
//                "Value": 1
//}

Varsayılan web seçenekleri

ASP.NET Core'un web uygulamaları için kullandığı varsayılan seçeneklerle seri hale getirmek istiyorsanız yeni JsonSerializerOptions.Web singleton'ı kullanın.

string webJson = JsonSerializer.Serialize(
    new { SomeValue = 42 },
    JsonSerializerOptions.Web // Defaults to camelCase naming policy.
    );
Console.WriteLine(webJson);
// {"someValue":42}

LINQ

Yeni yöntemler CountBy kullanıma AggregateBy sunulmuştur. Bu yöntemler aracılığıyla ara gruplandırmalar GroupByayırmaya gerek kalmadan durumu anahtara göre toplamayı mümkün hale getirir.

CountBy her anahtarın sıklığını hızlı bir şekilde hesaplamanızı sağlar. Aşağıdaki örnek, bir metin dizesinde en sık oluşan sözcüğü bulur.

string sourceText = """
    Lorem ipsum dolor sit amet, consectetur adipiscing elit.
    Sed non risus. Suspendisse lectus tortor, dignissim sit amet, 
    adipiscing nec, ultricies sed, dolor. Cras elementum ultrices amet diam.
""";

// Find the most frequent word in the text.
KeyValuePair<string, int> mostFrequentWord = sourceText
    .Split(new char[] { ' ', '.', ',' }, StringSplitOptions.RemoveEmptyEntries)
    .Select(word => word.ToLowerInvariant())
    .CountBy(word => word)
    .MaxBy(pair => pair.Value);

Console.WriteLine(mostFrequentWord.Key); // amet

AggregateBy daha genel amaçlı iş akışları uygulamanıza olanak tanır. Aşağıdaki örnek, belirli bir anahtarla ilişkili puanları nasıl hesaplayabileceğinizi gösterir.

(string id, int score)[] data =
    [
        ("0", 42),
        ("1", 5),
        ("2", 4),
        ("1", 10),
        ("0", 25),
    ];

var aggregatedData =
    data.AggregateBy(
        keySelector: entry => entry.id,
        seed: 0,
        (totalScore, curr) => totalScore + curr.score
        );

foreach (var item in aggregatedData)
{
    Console.WriteLine(item);
}
//(0, 67)
//(1, 15)
//(2, 4)

Index<TSource>(IEnumerable<TSource>) , numaralandırılabilir bir dizinin örtük dizinini hızlı bir şekilde ayıklamayı mümkün kılar. Artık bir koleksiyondaki öğeleri otomatik olarak dizine almak için aşağıdaki kod parçacığı gibi kod yazabilirsiniz.

IEnumerable<string> lines2 = File.ReadAllLines("output.txt");
foreach ((int index, string line) in lines2.Index())
{
    Console.WriteLine($"Line number: {index + 1}, Line: {line}");
}

Koleksiyonlar

PriorityQueue<TElement,TPriority> Ad alanında koleksiyon türü, kuyruktaki System.Collections.Generic bir öğenin önceliğini güncelleştirmek için kullanabileceğiniz yeni Remove(TElement, TElement, TPriority, IEqualityComparer<TElement>) bir yöntem içerir.

PriorityQueue.Remove() yöntemi

.NET 6, basit ve hızlı bir dizi yığını uygulaması sağlayan koleksiyonu tanıttı PriorityQueue<TElement,TPriority> . Dizi yığınlarının genel olarak sorunlarından biri, öncelik güncelleştirmelerini desteklememeleridir ve bu da Dijkstra algoritmasının varyasyonları gibi algoritmalarda kullanılmasını yasaklar.

Mevcut koleksiyonda verimli $O(\log n)$ öncelik güncelleştirmeleri uygulamak mümkün olmasa da, yeni PriorityQueue<TElement,TPriority>.Remove(TElement, TElement, TPriority, IEqualityComparer<TElement>) yöntem öncelik güncelleştirmelerini öykünmenizi mümkün kılar ($O(n)$ zamanında da olsa):

public static void UpdatePriority<TElement, TPriority>(
    this PriorityQueue<TElement, TPriority> queue,
    TElement element,
    TPriority priority
    )
{
    // Scan the heap for entries matching the current element.
    queue.Remove(element, out _, out _);
    // Re-insert the entry with the new priority.
    queue.Enqueue(element, priority);
}

Bu yöntem, asimptotik performansın engelleyici olmadığı bağlamlarda grafik algoritmaları uygulamak isteyen kullanıcıların engelini kaldırır. (Bu tür bağlamlar eğitim ve prototip oluşturma içerir.) Örneğin, dijkstra algoritmasının yeni API'yi kullanan bir oyuncak uygulaması aşağıda verilmiştır.

Şifreleme

Şifreleme için .NET 9 türüne CryptographicOperations yeni bir tek seferlik karma yöntemi ekler. Ayrıca KMAC algoritmasını kullanan yeni sınıflar ekler.

CryptographicOperations.HashData() yöntemi

.NET, karma işlevlerin ve ilgili işlevlerin birkaç statik "tek seferlik" uygulamasını içerir. Bu API'ler ve HMACSHA256.HashDataiçerirSHA256.HashData. Mümkün olan en iyi performansı sağlayıp ayırmaları azaltabilir veya ortadan kaldırabildiğinden, tek seferlik API'lerin kullanılması tercih edilir.

Geliştirici, çağıranın hangi karma algoritmayı kullanacağı tanımladığı karma oluşturmayı destekleyen bir API sağlamak istiyorsa, genellikle bir HashAlgorithmName bağımsız değişken kabul ederek yapılır. Ancak, bu deseni tek seferlik API'lerle kullanmak için mümkün HashAlgorithmName olan her geçişin yapılması ve ardından uygun yöntemin kullanılması gerekir. Bu sorunu çözmek için .NET 9, API'yi tanıtır CryptographicOperations.HashData . Bu API, kullanılan algoritmanın tarafından belirlendiği HashAlgorithmNametek seferlik bir giriş üzerinden karma veya HMAC oluşturmanızı sağlar.

static void HashAndProcessData(HashAlgorithmName hashAlgorithmName, byte[] data)
{
    byte[] hash = CryptographicOperations.HashData(hashAlgorithmName, data);
    ProcessHash(hash);
}

KMAC algoritması

.NET 9, NIST SP-800-185 tarafından belirtilen KMAC algoritmasını sağlar. KECCAK İleti Kimlik Doğrulama Kodu (KMAC), KECCAK'ı temel alan bir takma ad işlevi ve anahtarlı karma işlevidir.

Aşağıdaki yeni sınıflar KMAC algoritmasını kullanır. MAC oluşturmak için veri biriktirmek için örnekleri kullanın veya tek bir giriş üzerinde tek seferlik bir deneme için statik HashData yöntemi kullanın.

KMAC, OpenSSL 3.0 veya üzeri yüklü Linux'ta ve Windows 11 Derleme 26016 veya sonraki sürümlerde kullanılabilir. Platformun istenen algoritmayı desteklenip desteklemediğini belirlemek için statik IsSupported özelliğini kullanabilirsiniz.

if (Kmac128.IsSupported)
{
    byte[] key = GetKmacKey();
    byte[] input = GetInputToMac();
    byte[] mac = Kmac128.HashData(key, input, outputLength: 32);
}
else
{
    // Handle scenario where KMAC isn't available.
}

Yansıma

.NET Core sürümlerinde ve .NET 5-8 sürümlerinde, derleme oluşturma ve dinamik olarak oluşturulan türler için yansıma meta verilerini yayma desteği çalıştırılabilir AssemblyBuilderbir ile sınırlıydı. Derleme kaydetme desteğinin olmaması genellikle .NET Framework'ten .NET'e geçişte bulunan müşteriler için engelleyiciydi. .NET 9, yayılan bir derlemeyi kaydetmek için genel API'leri AssemblyBuilder ekler.

Yeni, kalıcı AssemblyBuilder uygulama çalışma zamanı ve platformdan bağımsızdır. Kalıcı AssemblyBuilder bir örnek oluşturmak için yeni AssemblyBuilder.DefinePersistedAssembly API'yi kullanın. Mevcut AssemblyBuilder.DefineDynamicAssembly API, derleme adını ve isteğe bağlı özel öznitelikleri kabul eder. Yeni API'yi kullanmak için temel çalışma zamanı türlerine başvurmak için kullanılan çekirdek derlemesini System.Private.CoreLibgeçirin. seçeneği AssemblyBuilderAccessyoktur. Şimdilik kalıcı AssemblyBuilder uygulama yalnızca kaydetmeyi destekler, çalıştırmayı desteklemez. Kalıcı AssemblyBuilderolan öğesinin bir örneğini oluşturduktan sonra modül, tür, yöntem veya sabit listesi tanımlama, IL yazma ve diğer tüm kullanımlar için sonraki adımlar değişmeden kalır. Bu, derlemeyi kaydetmek için mevcut System.Reflection.Emit kodu olduğu gibi kullanabileceğiniz anlamına gelir. Aşağıdaki kodda bir örneği gösterilmiştir.

public void CreateAndSaveAssembly(string assemblyPath)
{
    AssemblyBuilder ab = AssemblyBuilder.DefinePersistedAssembly(
        new AssemblyName("MyAssembly"),
        typeof(object).Assembly
        );
    TypeBuilder tb = ab.DefineDynamicModule("MyModule")
        .DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class);

    MethodBuilder mb = tb.DefineMethod(
        "SumMethod",
        MethodAttributes.Public | MethodAttributes.Static,
        typeof(int), [typeof(int), typeof(int)]
        );
    ILGenerator il = mb.GetILGenerator();
    il.Emit(OpCodes.Ldarg_0);
    il.Emit(OpCodes.Ldarg_1);
    il.Emit(OpCodes.Add);
    il.Emit(OpCodes.Ret);

    tb.CreateType();
    ab.Save(assemblyPath); // or could save to a Stream
}

public void UseAssembly(string assemblyPath)
{
    Assembly assembly = Assembly.LoadFrom(assemblyPath);
    Type type = assembly.GetType("MyType");
    MethodInfo method = type.GetMethod("SumMethod");
    Console.WriteLine(method.Invoke(null, [5, 10]));
}

Performans

.NET 9, uygulama performansını artırmayı hedefleyen 64 bit JIT derleyicisine yönelik iyileştirmeler içerir. Bu derleyici geliştirmeleri şunlardır:

Arm64 vektörleştirme , çalışma zamanının bir diğer yeni özelliğidir.

Döngü iyileştirmeleri

Döngüler için kod oluşturmanın geliştirilmesi .NET 9 için bir önceliktir ve 64 bit derleyici, indüksiyon değişkeni (IV) genişletme olarak adlandırılan yeni bir iyileştirme özelliğine sahiptir.

IV, içeren döngü yinelenirken değeri değişen bir değişkendir. Aşağıdaki for döngüde iv ifor (int i = 0; i < 10; i++): . Derleyici bir IV değerinin döngüsünün yinelemeleri üzerinde nasıl geliştiğini analiz edebilirse, ilgili ifadeler için daha yüksek performanslı kod üretebilir.

Bir dizide yineleyen aşağıdaki örneği göz önünde bulundurun:

static int Sum(int[] arr)
{
    int sum = 0;
    for (int i = 0; i < arr.Length; i++)
    {
        sum += arr[i];
    }

    return sum;
}

dizin değişkeninin iboyutu 4 bayttır. Derleme düzeyinde, 64 bit yazmaçlar genellikle x64'teki dizi dizinlerini tutmak için kullanılır ve önceki .NET sürümlerinde, derleyici tarafından oluşturulan kod dizi erişimi için 8 bayt'a kadar uzatılır i , ancak başka bir yerde 4 baytlık tamsayı olarak değerlendirilmeye i devam eder. Ancak, 8 bayta kadar uzatmak i için x64 üzerinde ek yönerge gerekir. IV genişletme ile 64 bit JIT derleyicisi artık döngü boyunca 8 bayta genişletilir i ve sıfır uzantıyı atlar. Diziler üzerinde döngü yapmak çok yaygındır ve bu yönerge kaldırma işleminin avantajları hızla eklenir.

Yerel AOT için inlining geliştirmeleri

bunlardan biri. NET'in 64 bit JIT derleyicisinin inliner'ı için hedefleri, bir yöntemin mümkün olduğunca inlined olmasını engelleyen birçok kısıtlamayı kaldırmaktır. .NET 9, Windows x64, Linux x64 ve Linux Arm64'te iş parçacığı yerel statiklerine erişimin hatlarını oluşturmanızı sağlar.

Sınıf üyeleri için static , üyenin tam olarak bir örneği, üyeyi "paylaşan" sınıfın tüm örnekleri arasında bulunur. Bir static üyenin değeri her iş parçacığı için benzersizse, bu değerin iş parçacığı yerel hale getirilmesi, bir eşzamanlılık temel öğesinin üyeye içeren iş parçacığından güvenli bir şekilde erişme static gereksinimini ortadan kaldırdığı için performansı geliştirebilir.

Daha önce, Yerel AOT ile derlenmiş programlarda iş parçacığı yerel statiklerine erişenler, iş parçacığı yerel depolamanın temel adresini almak için çalışma zamanına bir çağrı yaymak için 64 bit JIT derleyicisini gerektiriyor. Artık derleyici bu çağrıları satır içinde satır içi yapabilir ve bu verilere erişmek için çok daha az yönergeyle sonuçlanabilir.

PGO geliştirmeleri: Tür denetimleri ve atamaları

.NET 8 varsayılan olarak dinamik profil destekli iyileştirmeyi (PGO) etkinleştirdi. NET 9, 64 bit JIT derleyicisinin PGO uygulamasını genişleterek daha fazla kod deseninin profilini oluşturur. Katmanlı derleme etkinleştirildiğinde, 64 bit JIT derleyicisi zaten davranışının profilini almak için programınıza izleme ekler. İyileştirmelerle yeniden derlendiğinde derleyici, programınızın geçerli çalıştırmasına özgü kararlar almak için çalışma zamanında oluşturduğu profilden yararlanıyor. .NET 9'da 64 bit JIT derleyicisi, tür denetimlerinin performansını artırmak için PGO verilerini kullanır.

Bir nesnenin türünü belirlemek için çalışma zamanına bir çağrı yapılması gerekir ve bu da bir performans cezasıyla birlikte gelir. Bir nesnenin türünün denetlenmesi gerektiğinde, 64 bit JIT derleyicisi bu çağrıyı doğruluk adına yayar (derleyiciler genellikle olasılıksız görünseler bile olasılıkları göz ardı edemezler). Ancak PGO verileri bir nesnenin belirli bir tür olabileceğini gösteriyorsa, 64 bit JIT derleyicisi artık bu tür için ucuz bir şekilde denetim yapan hızlı bir yol yayar ve yalnızca gerekirse çalışma zamanına çağrının yavaş yoluna geri döner.

.NET kitaplıklarında Arm64 vektörleştirmesi

Yeni EncodeToUtf8 bir uygulama, 64 bit JIT derleyicisinin Arm64'te çoklu yazmaç yükleme/depolama yönergeleri yayma özelliğinden yararlanır. Bu davranış, programların daha az yönergeyle daha büyük veri öbeklerini işlemesine olanak tanır. Çeşitli etki alanlarındaki .NET uygulamaları, arm64 donanımında bu özellikleri destekleyen aktarım hızı iyileştirmelerini görmelidir. Bazı kıyaslamalar yürütme sürelerini yarıdan fazla azaltıyor.

.NET SDK

Birim testi

Bu bölümde. .NET 9'da birim testi güncelleştirmeleri açıklanmaktadır: testleri paralel olarak çalıştırma ve terminal günlükçü testi çıkışı.

Testleri paralel çalıştırma

.NET 9'da, dotnet test MSBuild ile tamamen tümleşiktir. MSBuild paralel olarak derlemeyi desteklediğinden, aynı proje için farklı hedef çerçevelerde testleri paralel olarak çalıştırabilirsiniz. Varsayılan olarak, MSBuild paralel işlemlerin sayısını bilgisayardaki işlemci sayısıyla sınırlar. -maxcpucount anahtarını kullanarak da kendi sınırınızı ayarlayabilirsiniz. Paralelliği geri çevirmek istiyorsanız, MSBuild özelliğini olarak falseayarlayınTestTfmsInParallel.

Terminal günlükçü test ekranı

için dotnet test test sonucu raporlaması artık doğrudan MSBuild terminal günlükçüsünde desteklenmektedir. Hem testler çalışırken (çalışan test adını görüntüler) hem detestler tamamlandıktan sonra (tüm test hataları daha iyi bir şekilde işlenir) tam özellikli test raporlaması elde edersiniz.

Terminal günlükçü hakkında daha fazla bilgi için bkz . dotnet derleme seçenekleri.

.NET aracı ileri sarma

.NET araçları , genel olarak veya yerel olarak yükleyebileceğiniz, ardından .NET SDK'sını ve yüklü .NET çalışma zamanlarını kullanarak çalıştırabileceğiniz çerçeveye bağımlı uygulamalardır. Tüm .NET uygulamaları gibi bu araçlar da .NET'in belirli bir ana sürümünü hedefler. Varsayılan olarak, uygulamalar .NET'in daha yeni sürümlerinde çalışmaz. Araç yazarları, MSBuild özelliğini ayarlayarak araçlarını .NET çalışma zamanının daha yeni sürümlerinde çalıştırmayı RollForward tercih edebildi. Ancak, tüm araçlar bunu yapmaz.

için dotnet tool install yeni bir seçenek, kullanıcıların .NET araçlarının nasıl çalıştırılacağına karar vermelerini sağlar. aracılığıyla dotnet tool installbir araç yüklediğinizde veya aracılığıyla bir araç dotnet tool run <toolname>çalıştırdığınızda adlı --allow-roll-forwardyeni bir bayrak belirtebilirsiniz. Bu seçenek, aracı ileri sarma modu Majorile yapılandırır. Bu mod, eşleşen .NET sürümü kullanılamıyorsa aracın .NET'in daha yeni bir ana sürümünde çalışmasına olanak tanır. Bu özellik, araç yazarlarının herhangi bir kodu değiştirmek zorunda kalmadan erken benimseyenlerin .NET araçlarını kullanmasına yardımcı olur.

Ayrıca bkz.