.NET 8 çalışma zamanındaki yenilikler

Bu makalede.NET 8 için .NET çalışma zamanındaki yeni özellikler açıklanmaktadır.

Performans iyileştirmeleri

.NET 8, kod oluşturma ve tam zamanında (JIT) derleme geliştirmeleri içerir:

  • Arm64 performans geliştirmeleri
  • SIMD geliştirmeleri
  • AVX-512 ISA uzantıları desteği (bkz . Vector512 ve AVX-512)
  • Bulutta yerel iyileştirmeler
  • JIT aktarım hızı geliştirmeleri
  • Döngü ve genel iyileştirmeler
  • ile işaretlenmiş alanlar için iyileştirilmiş erişim ThreadStaticAttribute
  • Ardışık kayıt ayırma. Arm64'te tablo vektörü araması için iki yönerge vardır ve bu yönerge, tanımlama grubu işlenenlerindeki tüm varlıkların ardışık yazmaçlarda bulunmasını gerektirir.
  • JIT/NativeAOT, derleme zamanında boyutlarını belirleyebiliyorsa simd ile karşılaştırma, kopyalama ve sıfırlama gibi bazı bellek işlemlerinin kaydını kaldırıp otomatik vektörleştirebilir.

Buna ek olarak, dinamik profil destekli iyileştirme (PGO) geliştirilmiştir ve artık varsayılan olarak etkindir. Artık etkinleştirmek için çalışma zamanı yapılandırma seçeneğini kullanmanız gerekmez. Dinamik PGO, katman 0 sırasında eklenen ek izlemelere göre kodu daha da iyileştirmek için katmanlı derleme ile el ele çalışır.

Dinamik PGO ortalama olarak performansı yaklaşık %15 artırır. Yaklaşık 4600 test içeren bir kıyaslama paketinde %23 oranında performans artışı %20 veya daha fazla oldu.

Codegen yapısı yükseltme

.NET 8, JIT'nin yapı değişkenlerini yükseltme yeteneğini genelleştiren kod oluşturma için yeni bir fiziksel yükseltme iyileştirme geçişi içerir. Bu iyileştirme (toplamların skaler değişimi olarak da adlandırılır), yapı değişkenlerinin alanlarını JIT'nin daha sonra mantık oluşturabileceği ve daha hassas bir şekilde iyileştirebileceği ilkel değişkenlerle değiştirir.

JIT bu iyileştirmeyi zaten desteklese de aşağıdakiler dahil olmak üzere çeşitli büyük sınırlamalar içerir:

  • Yalnızca dört veya daha az alana sahip yapılar için destekleniyordu.
  • Yalnızca her alan ilkel bir türse veya basit bir yapı ilkel türü sarmalarsa desteklenir.

Fiziksel yükseltme, uzun süredir devam eden JIT sorunlarını düzelten bu sınırlamaları kaldırır.

Atık toplama

.NET 8, bellek sınırını anında ayarlama özelliği ekler. Bu, talebin gelip gittiği bulut hizmeti senaryolarında kullanışlıdır. Maliyet etkin olması için, talep dalgalanmaları nedeniyle hizmetlerin kaynak tüketiminde ölçeği artırması ve azaltması gerekir. Bir hizmet talepte bir azalma algıladığında bellek sınırını azaltarak kaynak tüketiminin ölçeğini azaltabilir. Daha önce, çöp toplayıcı (GC) değişikliğin farkında olmadığından ve yeni sınırdan daha fazla bellek ayırabileceğinden bu başarısız olacaktı. Bu değişiklikle API'yi çağırarak RefreshMemoryLimit() GC'yi yeni bellek sınırıyla güncelleştirebilirsiniz.

Dikkat edilmesi gereken bazı sınırlamalar vardır:

  • 32 bit platformlarda (örneğin, Windows x86 ve Linux ARM), henüz yoksa .NET yeni bir yığın sabit sınırı oluşturamaz.
  • API, yenilemenin başarısız olduğunu gösteren sıfır olmayan bir durum kodu döndürebilir. Ölçek azaltma çok agresifse ve GC'nin manevrası için yer bırakmazsa bu durum oluşabilir. Bu durumda, geçerli bellek kullanımını küçültmek için aramayı GC.Collect(2, GCCollectionMode.Aggressive) göz önünde bulundurun ve sonra yeniden deneyin.
  • Başlangıç sırasında RefreshMemoryLimit GC'nin işlemin işleyebileceğine inandığı boyutun ötesinde bellek sınırını genişletirseniz çağrı başarılı olur, ancak sınır olarak algılanandan daha fazla bellek kullanamaz.

Aşağıdaki kod parçacığıNDA API'nin nasıl çağrılacakları gösterilmektedir.

GC.RefreshMemoryLimit();

Bellek sınırıyla ilgili GC yapılandırma ayarlarının bazılarını da yenileyebilirsiniz. Aşağıdaki kod parçacığı yığın sabit sınırını 100 mebibayt (MiB) olarak ayarlar:

AppContext.SetData("GCHeapHardLimit", (ulong)100 * 1_024 * 1_024);
GC.RefreshMemoryLimit();

Örneğin negatif yığın sabit sınırı yüzdeleri ve sabit sınırın çok düşük olması durumunda, API sabit sınır geçersizse bir InvalidOperationException oluşturabilir. Yeni AppData ayarları nedeniyle veya kapsayıcı bellek sınırı değişiklikleri nedeniyle yenilemenin ayarlanacağı yığın sabit sınırı önceden kaydedilmiş olandan daha düşükse bu durum oluşabilir.

Mobil uygulamalar için genelleştirme

iOS, tvOS ve MacCatalyst'te mobil uygulamalar, daha hafif bir ICU paketi kullanan yeni bir hibrit küreselleştirme modunu tercih edebilir. Karma modda genelleştirme verileri kısmen ICU paketinden, kısmen de Yerel API'lere yapılan çağrılardan alınır. Karma mod, mobil cihazlar tarafından desteklenen tüm yerel ayarlara hizmet eder.

Karma mod en çok sabit genelleştirme modunda çalışabilen ve mobil cihazlardaki ICU verilerinden kırpılan kültürleri kullanan uygulamalar için uygundur. Daha küçük bir ICU veri dosyası yüklemek istediğinizde de kullanabilirsiniz. (icudt_hybrid.dat dosyası, varsayılan ICU veri dosyasından %34,5 daha küçük icudt.dat.)

Karma genelleştirme modunu kullanmak için MSBuild özelliğini true olarak ayarlayın HybridGlobalization :

<PropertyGroup>
  <HybridGlobalization>true</HybridGlobalization>
</PropertyGroup>

Dikkat edilmesi gereken bazı sınırlamalar vardır:

  • Yerel API'nin sınırlamaları nedeniyle tüm genelleştirme API'leri karma modda desteklenmez.
  • Desteklenen API'lerden bazıları farklı davranışlara sahiptir.

Uygulamanızın etkilenip etkilenmediğini denetlemek için bkz . Davranış farklılıkları.

Kaynak tarafından oluşturulan COM birlikte çalışma

.NET 8, COM arabirimleriyle birlikte çalışma desteği sağlayan yeni bir kaynak oluşturucu içerir. Bir arabirimi kaynak oluşturucu için COM arabirimi olarak işaretlemek için kullanabilirsiniz GeneratedComInterfaceAttribute . Kaynak oluşturucu daha sonra C# kodundan yönetilmeyen koda çağrıyı etkinleştirmek için kod oluşturur. Ayrıca yönetilmeyen koddan C# içine çağrıyı etkinleştirmek için kod oluşturur. Bu kaynak oluşturucu ile LibraryImportAttributetümleşir ve türleri GeneratedComInterfaceAttribute ile parametre olarak kullanabilir ve -attributed yöntemlerinde LibraryImporttürleri döndürebilirsiniz.

using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;

[GeneratedComInterface]
[Guid("5401c312-ab23-4dd3-aa40-3cb4b3a4683e")]
partial interface IComInterface
{
    void DoWork();
}

internal partial class MyNativeLib
{
    [LibraryImport(nameof(MyNativeLib))]
    public static partial void GetComInterface(out IComInterface comInterface);
}

Kaynak oluşturucu ayrıca, özniteliğiyle GeneratedComInterfaceAttribute arabirimler uygulayan türleri yönetilmeyen koda geçirmenizi sağlamak için yeni GeneratedComClassAttribute özniteliği de destekler. Kaynak oluşturucu, arabirimleri uygulayan ve çağrıları yönetilen uygulamaya ileden bir COM nesnesini kullanıma açmak için gereken kodu oluşturur.

özniteliğine GeneratedComInterfaceAttribute sahip arabirimlerdeki yöntemler, ile aynı türleri LibraryImportAttributedestekler ve LibraryImportAttribute artık -attributed türlerini ve GeneratedComClass-attributed türlerini desteklerGeneratedComInterface.

C# kodunuz bir COM nesnesini yönetilmeyen koddan sarmak için yalnızca -attributed arabirimini kullanıyorsa GeneratedComInterfaceveya yönetilmeyen kodu kullanıma açmak için yönetilen nesneyi C# dilinden sarmalarsa, özelliğindeki Options seçenekleri kullanarak hangi kodun oluşturulacağını özelleştirebilirsiniz. Bu seçenekler, kullanılmayacağını bildiğiniz senaryolar için marshaller yazmanız gerekmeyeceği anlamına gelir.

Kaynak oluşturucu, COM nesne sarmalayıcılarını ve yönetilen nesne sarmalayıcılarını oluşturmak ve yönetmek için yeni StrategyBasedComWrappers türü kullanır. Bu yeni tür, COM birlikte çalışma için beklenen .NET kullanıcı deneyimini sağlarken ileri düzey kullanıcılar için özelleştirme noktaları sağlar. Uygulamanızın COM'dan türleri tanımlamak için kendi mekanizması varsa veya kaynak tarafından oluşturulan COM'un şu anda desteklemediği senaryoları desteklemeniz gerekiyorsa, senaryonuz için eksik özellikleri eklemek ve COM türleriniz için aynı .NET kullanıcı deneyimini elde etmek için yeni StrategyBasedComWrappers türü kullanmayı göz önünde bulundurun.

Visual Studio kullanıyorsanız yeni çözümleyiciler ve kod düzeltmeleri, mevcut COM birlikte çalışma kodunuzu kaynak tarafından oluşturulan birlikte çalışma özelliğini kullanacak şekilde dönüştürmenizi kolaylaştırır. olan her arabirimin ComImportAttributeyanında bir ampul, kaynak tarafından oluşturulan birlikte çalışabilirliğe dönüştürme seçeneği sunar. Düzeltme, özniteliğini kullanmak GeneratedComInterfaceAttribute için arabirimi değiştirir. ve ile GeneratedComInterfaceAttributebir arabirim uygulayan her sınıfın yanında, ampul özniteliğini türüne ekleme GeneratedComClassAttribute seçeneği sunar. Türleriniz dönüştürüldükten sonra, yöntemlerini kullanmak LibraryImportAttributeüzere taşıyabilirsinizDllImport.

Sınırlamalar

COM kaynak oluşturucu, BIR COM CoClass'ı etkinleştirmek için anahtar sözcüğünü new ve aşağıdaki API'leri kullanarak daire benzini desteklemez:

Yapılandırma bağlama kaynak oluşturucu

.NET 8, ASP.NET Core'da AOT ve kırpma dostu yapılandırma sağlamak için bir kaynak oluşturucu sunar. Oluşturucu, önceden var olan yansıma tabanlı uygulamaya bir alternatiftir.

Kaynak oluşturucu , Bindve Get için yoklamalar Configure(TOptions)tür bilgilerini almak için çağırır. Oluşturucu bir projede etkinleştirildiğinde, derleyici önceden var olan yansıma tabanlı çerçeve uygulamaları yerine oluşturulan yöntemleri örtük olarak seçer.

Oluşturucuyu kullanmak için kaynak kodu değişikliği gerekmez. AOT'd web uygulamalarında varsayılan olarak etkindir. Diğer proje türleri için kaynak oluşturucu varsayılan olarak kapalıdır, ancak özelliğini true proje dosyanızda olarak ayarlayarak EnableConfigurationBindingGenerator kabul edebilirsiniz:

<PropertyGroup>
    <EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
</PropertyGroup>

Aşağıdaki kod, bağlayıcıyı çağırma örneğini gösterir.

public class ConfigBindingSG
{
    static void RunIt(params string[] args)
    {
        WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
        IConfigurationSection section = builder.Configuration.GetSection("MyOptions");

        // !! Configure call - to be replaced with source-gen'd implementation
        builder.Services.Configure<MyOptions>(section);

        // !! Get call - to be replaced with source-gen'd implementation
        MyOptions? options0 = section.Get<MyOptions>();

        // !! Bind call - to be replaced with source-gen'd implementation
        MyOptions options1 = new();
        section.Bind(options1);

        WebApplication app = builder.Build();
        app.MapGet("/", () => "Hello World!");
        app.Run();
    }

    public class MyOptions
    {
        public int A { get; set; }
        public string S { get; set; }
        public byte[] Data { get; set; }
        public Dictionary<string, string> Values { get; set; }
        public List<MyClass> Values2 { get; set; }
    }

    public class MyClass
    {
        public int SomethingElse { get; set; }
    }
}

Core .NET kitaplıkları

Bu bölüm aşağıdaki alt konuları içerir:

Yansıma

İşlev işaretçileri .NET 5'te tanıtıldı, ancak ilgili yansıma desteği o sırada eklenmedi. İşlev işaretçisi kullanılırken typeof veya bir işlev işaretçisinde yansıma kullanılırken, typeof(delegate*<void>())FieldInfo.FieldType örneğin, sırasıyla bir IntPtr döndürüldü. .NET 8'den başlayarak, bunun yerine bir System.Type nesne döndürülür. Bu tür, çağırma kuralları, dönüş türü ve parametreler dahil olmak üzere işlev işaretçisi meta verilerine erişim sağlar.

Not

bir işlevin fiziksel adresi olan işlev işaretçisi örneği, olarak IntPtrtemsil edilmeye devam eder. Yalnızca yansıma türü değişti.

Yeni işlevsellik şu anda yalnızca CoreCLR çalışma zamanı ve MetadataLoadContextiçinde uygulandı.

yeni API'ler , ve gibi öğesine , System.Reflection.FieldInfove System.Reflection.ParameterInfogibi eklendiSystem.Type.System.Reflection.PropertyInfoIsFunctionPointer Aşağıdaki kod, yansıma için bazı yeni API'lerin nasıl kullanılacağını gösterir.

using System;
using System.Reflection;

// Sample class that contains a function pointer field.
public unsafe class UClass
{
    public delegate* unmanaged[Cdecl, SuppressGCTransition]<in int, void> _fp;
}

internal class FunctionPointerReflection
{
    public static void RunIt()
    {
        FieldInfo? fieldInfo = typeof(UClass).GetField(nameof(UClass._fp));

        // Obtain the function pointer type from a field.
        Type? fpType = fieldInfo?.FieldType;

        // New methods to determine if a type is a function pointer.
        Console.WriteLine(
        $"IsFunctionPointer: {fpType?.IsFunctionPointer}");
        Console.WriteLine(
            $"IsUnmanagedFunctionPointer: {fpType?.IsUnmanagedFunctionPointer}");

        // New methods to obtain the return and parameter types.
        Console.WriteLine($"Return type: {fpType?.GetFunctionPointerReturnType()}");

        if (fpType is not null)
        {
            foreach (Type parameterType in fpType.GetFunctionPointerParameterTypes())
            {
                Console.WriteLine($"Parameter type: {parameterType}");
            }
        }

        // Access to custom modifiers and calling conventions requires a "modified type".
        Type? modifiedType = fieldInfo?.GetModifiedFieldType();

        // A modified type forwards most members to its underlying type.
        Type? normalType = modifiedType?.UnderlyingSystemType;

        if (modifiedType is not null)
        {
            // New method to obtain the calling conventions.
            foreach (Type callConv in modifiedType.GetFunctionPointerCallingConventions())
            {
                Console.WriteLine($"Calling convention: {callConv}");
            }
        }

        // New method to obtain the custom modifiers.
        Type[]? modifiers =
            modifiedType?.GetFunctionPointerParameterTypes()[0].GetRequiredCustomModifiers();

        if (modifiers is not null)
        {
            foreach (Type modreq in modifiers)
            {
                Console.WriteLine($"Required modifier for first parameter: {modreq}");
            }
        }
    }
}

Önceki örnek aşağıdaki çıkışı oluşturur:

IsFunctionPointer: True
IsUnmanagedFunctionPointer: True
Return type: System.Void
Parameter type: System.Int32&
Calling convention: System.Runtime.CompilerServices.CallConvSuppressGCTransition
Calling convention: System.Runtime.CompilerServices.CallConvCdecl
Required modifier for first parameter: System.Runtime.InteropServices.InAttribute

Serileştirme

.NET 8'de serileştirme ve seri durumdan çıkarma işlevselliğinde birçok geliştirme yapılmıştır System.Text.Json . Örneğin, JSON yükünde olmayan üyelerin işlenmesini özelleştirebilirsiniz.

Aşağıdaki bölümlerde diğer serileştirme geliştirmeleri açıklanmaktadır:

Genel olarak JSON serileştirmesi hakkında daha fazla bilgi için bkz . .NET'te JSON serileştirme ve seri durumdan çıkarma.

Ek türler için yerleşik destek

Seri hale getirici aşağıdaki ek türler için yerleşik desteğe sahiptir.

  • Half, Int128ve UInt128 sayısal türler.

    Console.WriteLine(JsonSerializer.Serialize(
        [ Half.MaxValue, Int128.MaxValue, UInt128.MaxValue ]
    ));
    // [65500,170141183460469231731687303715884105727,340282366920938463463374607431768211455]
    
  • Memory<T> ve ReadOnlyMemory<T> değerlerini seçin. byte değerleri Base64 dizelerine, diğer türler ise JSON dizilerine serileştirilir.

    JsonSerializer.Serialize<ReadOnlyMemory<byte>>(new byte[] { 1, 2, 3 }); // "AQID"
    JsonSerializer.Serialize<Memory<int>>(new int[] { 1, 2, 3 }); // [1,2,3]
    

Kaynak oluşturucu

.NET 8, System.Text.Json kaynak oluşturucusunun Yansıma tabanlı seri hale getirici ile aynı yerel AOT deneyimini oluşturmayı hedefleyen geliştirmeleri içerir. Örneğin:

  • Kaynak oluşturucu artık ve init özellikleriyle required türleri serileştirmeyi destekliyor. Bunların ikisi de yansıma tabanlı serileştirmede zaten destekleniyordu.

  • Kaynak tarafından oluşturulan kodun biçimlendirmesi geliştirildi.

  • JsonSourceGenerationOptionsAttribute ile JsonSerializerOptionsözellik eşliği. Daha fazla bilgi için bkz . Seçenekleri belirtme (kaynak oluşturma).

  • Ek tanılamalar (SYSLIB1034 ve SYSLIB1039 gibi).

  • Yoksayılan veya erişilemeyen özellik türlerini eklemeyin.

  • Rastgele tür türleri içinde iç içe JsonSerializerContext bildirimleri için destek.

  • Zayıf türdeki kaynak oluşturma senaryolarında derleyici tarafından oluşturulan veya tanımlanamaz türler için destek. Derleyici tarafından oluşturulan türler kaynak oluşturucu tarafından açıkça belirtilemediklerinden, System.Text.Json artık çalışma zamanında en yakın üst düzey çözümlemesi gerçekleştiriyor. Bu çözümleme, değerin seri hale getirildiği en uygun üst türü belirler.

  • Yeni dönüştürücü türü JsonStringEnumConverter<TEnum>. Mevcut JsonStringEnumConverter sınıf Yerel AOT'de desteklenmez. Sabit listesi türlerinize aşağıdaki gibi not ekleyebilirsiniz:

    [JsonConverter(typeof(JsonStringEnumConverter<MyEnum>))]
    public enum MyEnum { Value1, Value2, Value3 }
    
    [JsonSerializable(typeof(MyEnum))]
    public partial class MyContext : JsonSerializerContext { }
    

    Daha fazla bilgi için bkz . Sabit listesi alanlarını dize olarak seri hale getirme.

  • Yeni JsonConverter.Type özellik, genel JsonConverter olmayan bir örneğin türünü aramanızı sağlar:

    Dictionary<Type, JsonConverter> CreateDictionary(IEnumerable<JsonConverter> converters)
        => converters.Where(converter => converter.Type != null)
                     .ToDictionary(converter => converter.Type!);
    

    özelliği, örnekler ve typeof(T) örnekler için döndürdüğünden JsonConverterFactorynullJsonConverter<T> null atanabilir.

Zincir kaynağı oluşturucuları

sınıfı, JsonSerializerOptions mevcut TypeInfoResolver özelliği tamamlayan yeni TypeInfoResolverChain bir özellik içerir. Bu özellikler, kaynak oluşturucuları zincirleme için sözleşme özelleştirmesinde kullanılır. Yeni özelliğin eklenmesi, tüm zincirlenmiş bileşenleri tek bir çağrı sitesinde belirtmeniz gerekmeyecek anlamına gelir; bunlar olgudan sonra eklenebilir. TypeInfoResolverChain ayrıca zincire giriş yapmanızı veya bileşenleri kaldırmanızı sağlar. Daha fazla bilgi için bkz . Kaynak oluşturucuları birleştirme.

Buna ek olarak, JsonSerializerOptions.AddContext<TContext>() artık kullanım dışıdır. ve TypeInfoResolverChain özellikleriyle TypeInfoResolver değiştirildi. Daha fazla bilgi için bkz . SYSLIB0049.

Arabirim hiyerarşileri

.NET 8, arabirim hiyerarşilerinden özellikleri seri hale getirme desteği ekler.

Aşağıdaki kod, hem hemen uygulanan arabirimden hem de temel arabiriminden özelliklerin seri hale getirildiği bir örneği gösterir.

public static void InterfaceHierarchies()
{
    IDerived value = new DerivedImplement { Base = 0, Derived = 1 };
    string json = JsonSerializer.Serialize(value);
    Console.WriteLine(json); // {"Derived":1,"Base":0}
}

public interface IBase
{
    public int Base { get; set; }
}

public interface IDerived : IBase
{
    public int Derived { get; set; }
}

public class DerivedImplement : IDerived
{
    public int Base { get; set; }
    public int Derived { get; set; }
}

Adlandırma ilkeleri

JsonNamingPolicy, (alt çizgi ile) ve kebab-case (kısa çizgiyle) özellik adı dönüştürmeleri için snake_case yeni adlandırma ilkeleri içerir. Bu ilkeleri mevcut JsonNamingPolicy.CamelCase ilkeye benzer şekilde kullanın:

var options = new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
};
JsonSerializer.Serialize(new { PropertyName = "value" }, options);
// { "property_name" : "value" }

Daha fazla bilgi için bkz . Yerleşik adlandırma ilkesi kullanma.

Salt okunur özellikler

Artık salt okunur alanlara veya özelliklere (erişimci olmayanlar) seri durumdan set çıkarabilirsiniz.

Bu desteği genel olarak kabul etmek için , olarak yeni bir seçenek PreferredObjectCreationHandlingJsonObjectCreationHandling.Populateayarlayın. Uyumluluk önemliyse, özniteliğini özellikleri doldurulacak belirli türlere veya tek tek özelliklere yerleştirerek [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] işlevselliği daha ayrıntılı bir şekilde etkinleştirebilirsiniz.

Örneğin, seri durumdan çıkararak iki salt okunur özelliğe sahip bir CustomerInfo türe dönüştüren aşağıdaki kodu göz önünde bulundurun.

public static void ReadOnlyProperties()
{
    CustomerInfo customer = JsonSerializer.Deserialize<CustomerInfo>("""
        { "Names":["John Doe"], "Company":{"Name":"Contoso"} }
        """)!;

    Console.WriteLine(JsonSerializer.Serialize(customer));
}

class CompanyInfo
{
    public required string Name { get; set; }
    public string? PhoneNumber { get; set; }
}

[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
class CustomerInfo
{
    // Both of these properties are read-only.
    public List<string> Names { get; } = new();
    public CompanyInfo Company { get; } = new()
    {
        Name = "N/A",
        PhoneNumber = "N/A"
    };
}

.NET 8'in öncesinde giriş değerleri yoksayılır ve Names ve Company özellikleri varsayılan değerlerini korurdu.

{"Names":[],"Company":{"Name":"N/A","PhoneNumber":"N/A"}}

Artık, seri durumdan çıkarma sırasında salt okunur özellikleri doldurmak için giriş değerleri kullanılır.

{"Names":["John Doe"],"Company":{"Name":"Contoso","PhoneNumber":"N/A"}}

Seri durumdan çıkarma davranışını doldurma hakkında daha fazla bilgi için bkz . Başlatılan özellikleri doldurma.

Yansıma tabanlı varsayılanı devre dışı bırakma

Artık yansıma tabanlı seri hale getiriciyi varsayılan olarak devre dışı bırakabilirsiniz. Bu devre dışı bırakma özelliği, özellikle kırpılmış ve Yerel AOT uygulamalarında kullanılmamış yansıma bileşenlerinin yanlışlıkla köklenmesinden kaçınmak için kullanışlıdır. Serileştirme ve seri durumdan çıkarma yöntemlerine bir JsonSerializerOptions bağımsız değişkenin geçirilmesini gerektirerek varsayılan yansıma tabanlı serileştirmeyi JsonSerializer devre dışı bırakmak için, MSBuild özelliğini proje dosyanızda olarak false ayarlayınJsonSerializerIsReflectionEnabledByDefault.

Özellik anahtarının değerini denetlemek için yeni IsReflectionEnabledByDefault API'yi kullanın. üzerinde System.Text.Jsonbir kitaplık yazarıysanız, yansıma bileşenlerini yanlışlıkla köklendirmeden varsayılanlarınızı yapılandırmak için özelliğine güvenebilirsiniz.

Daha fazla bilgi için bkz . Yansıma varsayılanlarını devre dışı bırakma.

Yeni JsonNode API yöntemleri

JsonNode ve System.Text.Json.Nodes.JsonArray türleri aşağıdaki yeni yöntemleri içerir.

public partial class JsonNode
{
    // Creates a deep clone of the current node and all its descendants.
    public JsonNode DeepClone();

    // Returns true if the two nodes are equivalent JSON representations.
    public static bool DeepEquals(JsonNode? node1, JsonNode? node2);

    // Determines the JsonValueKind of the current node.
    public JsonValueKind GetValueKind(JsonSerializerOptions options = null);

    // If node is the value of a property in the parent
    // object, returns its name.
    // Throws InvalidOperationException otherwise.
    public string GetPropertyName();

    // If node is the element of a parent JsonArray,
    // returns its index.
    // Throws InvalidOperationException otherwise.
    public int GetElementIndex();

    // Replaces this instance with a new value,
    // updating the parent object/array accordingly.
    public void ReplaceWith<T>(T value);

    // Asynchronously parses a stream as UTF-8 encoded data
    // representing a single JSON value into a JsonNode.
    public static Task<JsonNode?> ParseAsync(
        Stream utf8Json,
        JsonNodeOptions? nodeOptions = null,
        JsonDocumentOptions documentOptions = default,
        CancellationToken cancellationToken = default);
}

public partial class JsonArray
{
    // Returns an IEnumerable<T> view of the current array.
    public IEnumerable<T> GetValues<T>();
}

Genel olmayan üyeler

ve JsonConstructorAttribute öznitelik ek açıklamalarını kullanarak JsonIncludeAttribute belirli bir tür için serileştirme sözleşmesine genel olmayan üyeleri seçebilirsiniz.

public static void NonPublicMembers()
{
    string json = JsonSerializer.Serialize(new MyPoco(42));
    Console.WriteLine(json);
    // {"X":42}

    JsonSerializer.Deserialize<MyPoco>(json);
}

public class MyPoco
{
    [JsonConstructor]
    internal MyPoco(int x) => X = x;

    [JsonInclude]
    internal int X { get; }
}

Daha fazla bilgi için bkz . Sabit türleri ve ortak olmayan üyeleri ve erişimcileri kullanma.

Akış seri durumdan çıkarma API'leri

.NET 8, örneğin GetFromJsonAsAsyncEnumerableyeni IAsyncEnumerable<T> akış seri durumdan çıkarma uzantısı yöntemlerini içerir. örneğinHttpClientJsonExtensions.GetFromJsonAsync, döndüren Task<TResult>benzer yöntemler mevcut. Yeni uzantı yöntemleri akış API'lerini çağırır ve döndürür IAsyncEnumerable<T>.

Aşağıdaki kod, yeni uzantı yöntemlerini nasıl kullanabileceğinizi gösterir.

public async static void StreamingDeserialization()
{
    const string RequestUri = "https://api.contoso.com/books";
    using var client = new HttpClient();
    IAsyncEnumerable<Book?> books = client.GetFromJsonAsAsyncEnumerable<Book>(RequestUri);

    await foreach (Book? book in books)
    {
        Console.WriteLine($"Read book '{book?.title}'");
    }
}

public record Book(int id, string title, string author, int publishedYear);

WithAddedModifier uzantısı yöntemi

Yeni WithAddedModifier(IJsonTypeInfoResolver, Action<JsonTypeInfo>) uzantı yöntemi, rastgele IJsonTypeInfoResolver örneklerin serileştirme sözleşmelerinde kolayca değişiklikler yapmanıza olanak tanır.

var options = new JsonSerializerOptions
{
    TypeInfoResolver = MyContext.Default
        .WithAddedModifier(static typeInfo =>
        {
            foreach (JsonPropertyInfo prop in typeInfo.Properties)
            {
                prop.Name = prop.Name.ToUpperInvariant();
            }
        })
};

Yeni JsonContent.Create aşırı yüklemeleri

Artık kırpma güvenli veya kaynak tarafından oluşturulan sözleşmeleri kullanarak örnekler oluşturabilirsiniz JsonContent . Yeni yöntemler şunlardır:

var book = new Book(id: 42, "Title", "Author", publishedYear: 2023);
HttpContent content = JsonContent.Create(book, MyContext.Default.Book);

public record Book(int id, string title, string author, int publishedYear);

[JsonSerializable(typeof(Book))]
public partial class MyContext : JsonSerializerContext
{
}

JsonSerializerOptions örneğini dondurma

Aşağıdaki yeni yöntemler bir JsonSerializerOptions örneğin ne zaman dondurulduğunda denetlemenizi sağlar:

  • JsonSerializerOptions.MakeReadOnly()

    Bu aşırı yükleme, kırpma güvenli olacak şekilde tasarlanmıştır ve bu nedenle seçenekler örneğinin bir çözümleyiciyle yapılandırılmadığı durumlarda bir özel durum oluşturur.

  • JsonSerializerOptions.MakeReadOnly(Boolean)

    Bu aşırı yüklemeye geçerseniz true , eksikse seçenekler örneğini varsayılan yansıma çözümleyicisiyle doldurur. Bu yöntem işaretlenir RequiresUnreferenceCode/RequiresDynamicCode ve bu nedenle Yerel AOT uygulamaları için uygun değildir.

Yeni IsReadOnly özellik, seçenekler örneğinin dondurularak dondurulmadığını denetlemenize olanak tanır.

Zaman soyutlaması

Yeni TimeProvider sınıf ve ITimer arabirim, test senaryolarında zaman ile dalga geçmenizi sağlayan zaman soyutlama işlevi ekler. Buna ek olarak, ve Task.WaitAsynckullanarak Task.Delay zaman ilerlemesine dayanan sahte Task işlemler için zaman soyutlama kullanabilirsiniz. Zaman soyutlaması aşağıdaki temel zaman işlemlerini destekler:

  • Yerel ve UTC saatini alma
  • Performansı ölçmek için zaman damgası alma
  • Zamanlayıcı oluşturma

Aşağıdaki kod parçacığında bazı kullanım örnekleri gösterilmektedir.

// Get system time.
DateTimeOffset utcNow = TimeProvider.System.GetUtcNow();
DateTimeOffset localNow = TimeProvider.System.GetLocalNow();

TimerCallback callback = s => ((State)s!).Signal();

// Create a timer using the time provider.
ITimer timer = _timeProvider.CreateTimer(
    callback, null, TimeSpan.Zero, Timeout.InfiniteTimeSpan);

// Measure a period using the system time provider.
long providerTimestamp1 = TimeProvider.System.GetTimestamp();
long providerTimestamp2 = TimeProvider.System.GetTimestamp();

TimeSpan period = _timeProvider.GetElapsedTime(providerTimestamp1, providerTimestamp2);
// Create a time provider that works with a
// time zone that's different than the local time zone.
private class ZonedTimeProvider(TimeZoneInfo zoneInfo) : TimeProvider()
{
    private readonly TimeZoneInfo _zoneInfo = zoneInfo ?? TimeZoneInfo.Local;

    public override TimeZoneInfo LocalTimeZone => _zoneInfo;

    public static TimeProvider FromLocalTimeZone(TimeZoneInfo zoneInfo) =>
        new ZonedTimeProvider(zoneInfo);
}

UTF8 geliştirmeleri

Türünüzün hedef yayılma alanına dize benzeri bir gösterimini yazmayı etkinleştirmek istiyorsanız, türünüzde yeni IUtf8SpanFormattable arabirimi uygulayın. Bu yeni arabirim ile yakından ilişkilidir ISpanFormattable, ancak UTF16 ve Span<byte> yerine UTF8'i Span<char>hedefler.

IUtf8SpanFormattabletüm temel türler (artı diğerleri) üzerinde , veya Span<byte>hedeflenen stringSpan<char>tam olarak aynı paylaşılan mantıkla uygulanmıştır. Tüm biçimler (yeni "B" ikili tanımlayıcısı dahil) ve tüm kültürler için tam desteğe sahiptir. Bu, artık , , , , GuidDateTimeDateTimeOffsetDoubleCharIPAddressIPNetworkHalfDateOnlyDecimal, Int16, TimeOnlyRuneSByteInt64IntPtrInt128NFloatInt32Single, UInt64TimeSpanUIntPtrUInt16UInt128UInt32ve Versionkaynaklarından Bytedoğrudan UTF8'e biçimlendirebileceğiniz anlamına gelir. Complex

Yeni Utf8.TryWrite yöntemler, UTF16 tabanlı mevcut MemoryExtensions.TryWrite yöntemlere UTF8 tabanlı bir karşılık sağlar. Karmaşık bir ifadeyi doğrudan UTF8 bayt aralığına biçimlendirmek için ilişkilendirilmiş dize söz dizimini kullanabilirsiniz, örneğin:

static bool FormatHexVersion(
    short major,
    short minor,
    short build,
    short revision,
    Span<byte> utf8Bytes,
    out int bytesWritten) =>
    Utf8.TryWrite(
        utf8Bytes,
        CultureInfo.InvariantCulture,
        $"{major:X4}.{minor:X4}.{build:X4}.{revision:X4}",
        out bytesWritten);

Uygulama, biçim değerlerini tanır IUtf8SpanFormattable ve UTF8 gösterimlerini doğrudan hedef yayılmaya yazmak için uygulamalarını kullanır.

Uygulama ayrıca yeni yöntemi de kullanır Encoding.TryGetBytes(ReadOnlySpan<Char>, Span<Byte>, Int32) . Bu yöntem, karşılık geleniyle Encoding.TryGetChars(ReadOnlySpan<Byte>, Span<Char>, Int32) birlikte bir hedef yayılma alanına kodlamayı ve kod çözmeyi destekler. Span, sonuçta elde edilen durumu tutacak kadar uzun değilse, yöntemler bir özel durum atmak yerine döndürür false .

Rastgele çalışma yöntemleri

System.Random ve System.Security.Cryptography.RandomNumberGenerator türleri, rastgelelik ile çalışmak için iki yeni yöntem sağlar.

GetItems<T>()

Yeni System.Random.GetItems ve System.Security.Cryptography.RandomNumberGenerator.GetItems yöntemleri, bir giriş kümesinden belirli sayıda öğeyi rastgele seçmenize olanak sağlar. Aşağıdaki örnekte, bir diziye rastgele 31 öğe eklemek için nasıl kullanılacağı System.Random.GetItems<T>() (özellik tarafından Random.Shared sağlanan örnekte) gösterilmektedir. Bu örnek, oyuncuların renkli düğme dizisini hatırlaması gereken bir "Simon" oyununda kullanılabilir.

private static ReadOnlySpan<Button> s_allButtons = new[]
{
    Button.Red,
    Button.Green,
    Button.Blue,
    Button.Yellow,
};

// ...

Button[] thisRound = Random.Shared.GetItems(s_allButtons, 31);
// Rest of game goes here ...

<Karıştırma T>()

Yeni Random.Shuffle ve RandomNumberGenerator.Shuffle<T>(Span<T>) yöntemleri, bir yayılma alanının sırasını rastgele oluşturmanıza olanak sağlar. Bu yöntemler makine öğrenmesindeki eğitim yanlılığını azaltmak için kullanışlıdır (dolayısıyla ilk şey her zaman eğitim değildir ve son şey her zaman test edilir).

YourType[] trainingData = LoadTrainingData();
Random.Shared.Shuffle(trainingData);

IDataView sourceData = mlContext.Data.LoadFromEnumerable(trainingData);

DataOperationsCatalog.TrainTestData split = mlContext.Data.TrainTestSplit(sourceData);
model = chain.Fit(split.TrainSet);

IDataView predictions = model.Transform(split.TestSet);
// ...

Performans odaklı türler

.NET 8, uygulama performansını artırmayı amaçlayan çeşitli yeni türler sağlar.

  • Yeni System.Collections.Frozen ad alanı koleksiyon türlerini FrozenDictionary<TKey,TValue> ve FrozenSet<T>içerir. Bu türler, koleksiyon oluşturulduktan sonra anahtarlarda ve değerlerde herhangi bir değişikliğe izin vermez. Bu gereksinim daha hızlı okuma işlemlerine olanak tanır (örneğin, TryGetValue()). Bu türler özellikle ilk kullanımda doldurulan ve daha sonra uzun süreli bir hizmet süresi boyunca kalıcı hale gelen koleksiyonlar için kullanışlıdır, örneğin:

    private static readonly FrozenDictionary<string, bool> s_configurationData =
        LoadConfigurationData().ToFrozenDictionary(optimizeForReads: true);
    
    // ...
    if (s_configurationData.TryGetValue(key, out bool setting) && setting)
    {
        Process();
    }
    
  • Geçirilen koleksiyondaki herhangi bir değerin ilk oluşumunu aramak gibi MemoryExtensions.IndexOfAny yöntemler. Yeni System.Buffers.SearchValues<T> tür, bu tür yöntemlere geçirilecek şekilde tasarlanmıştır. Buna karşılık, .NET 8, yeni türün bir örneğini kabul eden gibi MemoryExtensions.IndexOfAny yöntemlerin yeni aşırı yüklemelerini ekler. örneğini SearchValues<T>oluşturduğunuzda, sonraki aramaları iyileştirmek için gerekli olan tüm veriler o anda türetilir ve bu da işin önden yapıldığı anlamına gelir.

  • Yeni System.Text.CompositeFormat tür, derleme zamanında bilinmeyen biçim dizelerini iyileştirmek için kullanışlıdır (örneğin, biçim dizesi bir kaynak dosyasından yüklenirse). Dizeyi ayrıştırma gibi işleri yapmak için biraz daha fazla zaman harcanıyor, ancak her kullanımda çalışmanın yapılmasından tasarruf ediyor.

    private static readonly CompositeFormat s_rangeMessage =
        CompositeFormat.Parse(LoadRangeMessageResource());
    
    // ...
    static string GetMessage(int min, int max) =>
        string.Format(CultureInfo.InvariantCulture, s_rangeMessage, min, max);
    
  • Yeni System.IO.Hashing.XxHash3 ve System.IO.Hashing.XxHash128 türleri hızlı XXH3 ve XXH128 karma algoritmalarının uygulamalarını sağlar.

System.Numerics ve System.Runtime.Intrinsics

Bu bölümde ve System.Runtime.Intrinsics ad alanlarıyla ilgili System.Numerics iyileştirmeler açıklanmıştır.

  • Vector256<T>, Matrix3x2ve Matrix4x4 .NET 8'de donanım hızlandırmayı geliştirdi. Örneğin, Vector256<T> mümkün olduğunca şirket içinde işlemler olacak 2x Vector128<T> şekilde yeniden tahmin edildi. Bu, arm64 gibi ancak Vector256.IsHardwareAccelerated == falsebazı işlevlerin Vector128.IsHardwareAccelerated == true kısmi olarak hızlanmasını sağlar.
  • Donanım iç bilgileri artık özniteliğiyle ConstExpected ek açıklama ekleniyor. Bu, kullanıcıların temel donanım sabit beklediğinde ve bu nedenle sabit olmayan bir değerin beklenmedik bir şekilde performansa zarar verebileceğinin farkında olmasını sağlar.
  • Lerp(TSelf, TSelf, TSelf)Lerp API'ye ve bu nedenle (Single), double (Double) ve Halföğesine float eklendiIFloatingPointIeee754<TSelf>. Bu API, iki değer arasındaki doğrusal ilişkilendirmenin verimli ve doğru bir şekilde gerçekleştirilmesini sağlar.

Vector512 ve AVX-512

.NET Core 3.0, x86/x64 için platforma özgü donanım iç API'lerini içerecek şekilde genişletilmiş SIMD desteği. .NET 5, Arm64 için destek ekledi ve .NET 7, platformlar arası donanım iç bilgilerini ekledi. .NET 8, Intel Advanced Vector Extensions 512 (AVX-512) yönergelerini kullanıma sunarak ve destekleyerek Vector512<T>SIMD desteği sağlar.

Özel olarak, .NET 8, AVX-512'nin aşağıdaki temel özellikleri için destek içerir:

  • 512 bit vektör işlemleri
  • Ek 16 SIMD yazmaç
  • 128 bit, 256 bit ve 512 bit vektörler için ek yönergeler sağlanabilir

İşlevselliği destekleyen bir donanımınız varsa, Vector512.IsHardwareAccelerated şimdi bildirir true.

.NET 8 ayrıca ad alanının altına platforma System.Runtime.Intrinsics.X86 özgü birkaç sınıf ekler:

Bu sınıflar, yalnızca 64 bit işlemler için kullanılabilen yönergeler için bir IsSupported özelliği ve iç içe Avx512F.X64 geçmiş sınıfı kullanıma sunmaları nedeniyle diğer yönerge kümesi mimarileriyle (ISA' lar) aynı genel şekli izler. Ayrıca, her sınıfın ilgili yönerge kümesi için (vektör uzunluğu) uzantılarını kullanıma Avx512VL sunan iç içe geçmiş Avx512F.VL bir sınıfı vardır.

Kodunuzda açıkça -specific veya Avx512F-specific yönergelerini kullanmasanız Vector512bile, büyük olasılıkla yeni AVX-512 desteğinden yararlanmaya devam edersiniz. JIT, veya Vector256<T>kullanırken Vector128<T> ek yazmaçlardan ve yönergelerden örtük olarak yararlanabilir. Temel sınıf kitaplığı, ilkel türler için kullanıma sunulan matematik API'lerinin çoğunda ve ReadOnlySpan<T> tarafından Span<T> kullanıma sunulan çoğu işlemde bu donanım iç öğelerini dahili olarak kullanır.

Veri doğrulaması

Ad alanı, System.ComponentModel.DataAnnotations bulutta yerel hizmetlerde doğrulama senaryolarına yönelik yeni veri doğrulama öznitelikleri içerir. Önceden var olan DataAnnotations doğrulayıcılar, form üzerindeki alanlar gibi tipik UI veri girişi doğrulamasına yönelik olsa da, yeni öznitelikler yapılandırma seçenekleri gibi kullanıcı girişi olmayan verileri doğrulamak için tasarlanmıştır. Yeni özniteliklere ek olarak ve RequiredAttribute türlerine RangeAttribute yeni özellikler eklendi.

Yeni API Açıklama
RangeAttribute.MinimumIsExclusive
RangeAttribute.MaximumIsExclusive
sınırların izin verilen aralığa dahil edilip edilmeyeceğini belirtir.
System.ComponentModel.DataAnnotations.LengthAttribute Dizeler veya koleksiyonlar için hem alt hem de üst sınırları belirtir. Örneğin, [Length(10, 20)] bir koleksiyonda en az 10 öğe ve en fazla 20 öğe gerektirir.
System.ComponentModel.DataAnnotations.Base64StringAttribute Bir dizenin geçerli bir Base64 gösterimi olduğunu doğrular.
System.ComponentModel.DataAnnotations.AllowedValuesAttribute
System.ComponentModel.DataAnnotations.DeniedValuesAttribute
İzin verme listelerini ve reddetme listelerini sırasıyla belirtin. Örneğin, [AllowedValues("apple", "banana", "mango")].

Ölçümler

Yeni API'ler, oluştururken ve Instrument nesnelerine anahtar-değer çifti etiketleri eklemenize Meter olanak sağlar. Yayımlanan ölçüm ölçümlerinin toplayıcıları, toplanan değerleri ayırt etmek için etiketleri kullanabilir.

var options = new MeterOptions("name")
{
    Version = "version",
    // Attach these tags to the created meter.
    Tags = new TagList()
    {
        { "MeterKey1", "MeterValue1" },
        { "MeterKey2", "MeterValue2" }
    }
};

Meter meter = meterFactory!.Create(options);

Counter<int> counterInstrument = meter.CreateCounter<int>(
    "counter", null, null, new TagList() { { "counterKey1", "counterValue1" } }
);
counterInstrument.Add(1);

Yeni API'ler şunlardır:

Şifreleme

.NET 8, SHA-3 karma temelleri için destek ekler. (SHA-3 şu anda OpenSSL 1.1.1 veya üzeri ve Windows 11 Derleme 25324 veya sonraki sürümleriyle Linux tarafından desteklenmektedir.) SHA-2'nin kullanılabildiği API'ler artık SHA-3 övgüsdür. Bu, karma oluşturma HMACSHA3_256HMACSHA3_384için , SHA3_384ve SHA3_512 , ve HMACSHA3_512 HMAC; HashAlgorithmName.SHA3_256, HashAlgorithmName.SHA3_384, ve HashAlgorithmName.SHA3_512 algoritmanın yapılandırılabilir olduğu karma oluşturma için; ve RSAEncryptionPadding.OaepSHA3_256, RSAEncryptionPadding.OaepSHA3_384ve RSAEncryptionPadding.OaepSHA3_512 RSA OAEP şifrelemesi için içerirSHA3_256.

Aşağıdaki örnekte, platformun SHA-3'ü desteklenip desteklemediğini belirlemek için özelliği de dahil olmak üzere SHA3_256.IsSupported API'lerin nasıl kullanılacağı gösterilmektedir.

// Hashing example
if (SHA3_256.IsSupported)
{
    byte[] hash = SHA3_256.HashData(dataToHash);
}
else
{
    // ...
}

// Signing example
if (SHA3_256.IsSupported)
{
     using ECDsa ec = ECDsa.Create(ECCurve.NamedCurves.nistP256);
     byte[] signature = ec.SignData(dataToBeSigned, HashAlgorithmName.SHA3_256);
}
else
{
    // ...
}

SHA-3 desteği şu anda şifreleme temel öğelerini desteklemeyi hedeflemektedir. Üst düzey yapıların ve protokollerin başlangıçta SHA-3'i tam olarak desteklemesi beklenmiyor. Bu protokoller X.509 sertifikalarını SignedXmlve COSE'yi içerir.

HTTPS proxy desteği

Şimdiye kadar, tümünü destekleyen HttpClient proxy türleri, HTTPS URI'leri için bile istemcinin hangi siteye bağlandığını görmek için bir "ortadaki adam"a izin verdi. HttpClientartık tüm isteklerin tam gizlilikle işlenebilmesi için istemci ile ara sunucu arasında şifreli bir kanal oluşturan HTTPS proxy'yi destekliyor.

HTTPS ara sunucusunu etkinleştirmek için ortam değişkenini all_proxy ayarlayın veya ara sunucuyu program aracılığıyla denetlemek için sınıfını kullanın WebProxy .

Unix: export all_proxy=https://x.x.x.x:3218 Windows: set all_proxy=https://x.x.x.x:3218

Ara sunucuyu program aracılığıyla denetlemek için sınıfını WebProxy da kullanabilirsiniz.

Akış tabanlı ZipFile yöntemleri

.NET 8, bir dizine dahil edilen tüm dosyaları toplamanıza ve sıkıştırmanıza ve ardından sonuçta elde edilen zip dosyasını sağlanan akışta depolamanıza olanak sağlayan yeni aşırı yüklemeleri ZipFile.CreateFromDirectory içerir. Benzer şekilde, yeni ZipFile.ExtractToDirectory aşırı yüklemeler sıkıştırılmış dosya içeren bir akış sağlamanıza ve içeriğini dosya sistemine ayıklamanıza olanak sağlar. Yeni aşırı yüklemeler şunlardır:

namespace System.IO.Compression;

public static partial class ZipFile
{
    public static void CreateFromDirectory(
        string sourceDirectoryName, Stream destination);

    public static void CreateFromDirectory(
        string sourceDirectoryName,
        Stream destination,
        CompressionLevel compressionLevel,
        bool includeBaseDirectory);

    public static void CreateFromDirectory(
        string sourceDirectoryName,
        Stream destination,
        CompressionLevel compressionLevel,
        bool includeBaseDirectory,
    Encoding? entryNameEncoding);

    public static void ExtractToDirectory(
        Stream source, string destinationDirectoryName) { }

    public static void ExtractToDirectory(
        Stream source, string destinationDirectoryName, bool overwriteFiles) { }

    public static void ExtractToDirectory(
        Stream source, string destinationDirectoryName, Encoding? entryNameEncoding) { }

    public static void ExtractToDirectory(
        Stream source, string destinationDirectoryName, Encoding? entryNameEncoding, bool overwriteFiles) { }
}

Disk alanı kısıtlandığında bu yeni API'ler yararlı olabilir, çünkü diski ara adım olarak kullanmaktan kaçınırlar.

Uzantı kitaplıkları

Bu bölüm aşağıdaki alt konuları içerir:

Anahtarlı DI hizmetleri

Anahtarlı bağımlılık ekleme (DI) hizmetleri, anahtarları kullanarak DI hizmetlerini kaydetmek ve almak için bir araç sağlar. Anahtarları kullanarak, hizmetleri kaydetme ve kullanma şeklinizi kapsamlayabilirsiniz. Yeni API'lerden bazıları şunlardır:

Aşağıdaki örnekte anahtarlı DI hizmetlerinin nasıl kullanılacağı gösterilmektedir.

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<BigCacheConsumer>();
builder.Services.AddSingleton<SmallCacheConsumer>();
builder.Services.AddKeyedSingleton<ICache, BigCache>("big");
builder.Services.AddKeyedSingleton<ICache, SmallCache>("small");
WebApplication app = builder.Build();
app.MapGet("/big", (BigCacheConsumer data) => data.GetData());
app.MapGet("/small", (SmallCacheConsumer data) => data.GetData());
app.MapGet("/big-cache", ([FromKeyedServices("big")] ICache cache) => cache.Get("data"));
app.MapGet("/small-cache", (HttpContext httpContext) => httpContext.RequestServices.GetRequiredKeyedService<ICache>("small").Get("data"));
app.Run();

class BigCacheConsumer([FromKeyedServices("big")] ICache cache)
{
    public object? GetData() => cache.Get("data");
}

class SmallCacheConsumer(IServiceProvider serviceProvider)
{
    public object? GetData() => serviceProvider.GetRequiredKeyedService<ICache>("small").Get("data");
}

public interface ICache
{
    object Get(string key);
}

public class BigCache : ICache
{
    public object Get(string key) => $"Resolving {key} from big cache.";
}

public class SmallCache : ICache
{
    public object Get(string key) => $"Resolving {key} from small cache.";
}

Daha fazla bilgi için bkz . dotnet/runtime#64427.

Barındırılan yaşam döngüsü hizmetleri

Barındırılan hizmetler artık uygulama yaşam döngüsü sırasında yürütme için daha fazla seçeneğe sahiptir. IHostedServiceve sağlandı StartAsync ve şimdi IHostedLifecycleService şu ek yöntemleri StopAsyncsağlıyor:

Bu yöntemler sırasıyla mevcut noktalardan önce ve sonra çalışır.

Aşağıdaki örnekte yeni API'lerin nasıl kullanılacağı gösterilmektedir.

using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

internal class HostedLifecycleServices
{
    public async static void RunIt()
    {
        IHostBuilder hostBuilder = new HostBuilder();
        hostBuilder.ConfigureServices(services =>
        {
            services.AddHostedService<MyService>();
        });

        using (IHost host = hostBuilder.Build())
        {
            await host.StartAsync();
        }
    }

    public class MyService : IHostedLifecycleService
    {
        public Task StartingAsync(CancellationToken cancellationToken) => /* add logic here */ Task.CompletedTask;
        public Task StartAsync(CancellationToken cancellationToken) => /* add logic here */ Task.CompletedTask;
        public Task StartedAsync(CancellationToken cancellationToken) => /* add logic here */ Task.CompletedTask;
        public Task StopAsync(CancellationToken cancellationToken) => /* add logic here */ Task.CompletedTask;
        public Task StoppedAsync(CancellationToken cancellationToken) => /* add logic here */ Task.CompletedTask;
        public Task StoppingAsync(CancellationToken cancellationToken) => /* add logic here */ Task.CompletedTask;
    }
}

Daha fazla bilgi için bkz . dotnet/runtime#86511.

Seçenekler doğrulaması

Kaynak oluşturucu

Başlangıç ek yükünü azaltmak ve doğrulama özellik kümesini geliştirmek için doğrulama mantığını uygulayan bir kaynak kodu oluşturucuyu kullanıma aldık. Aşağıdaki kod örnek modelleri ve doğrulayıcı sınıflarını gösterir.

public class FirstModelNoNamespace
{
    [Required]
    [MinLength(5)]
    public string P1 { get; set; } = string.Empty;

    [Microsoft.Extensions.Options.ValidateObjectMembers(
        typeof(SecondValidatorNoNamespace))]
    public SecondModelNoNamespace? P2 { get; set; }
}

public class SecondModelNoNamespace
{
    [Required]
    [MinLength(5)]
    public string P4 { get; set; } = string.Empty;
}

[OptionsValidator]
public partial class FirstValidatorNoNamespace
    : IValidateOptions<FirstModelNoNamespace>
{
}

[OptionsValidator]
public partial class SecondValidatorNoNamespace
    : IValidateOptions<SecondModelNoNamespace>
{
}

Uygulamanız bağımlılık ekleme kullanıyorsa aşağıdaki örnek kodda gösterildiği gibi doğrulamayı ekleyebilirsiniz.

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.Configure<FirstModelNoNamespace>(
    builder.Configuration.GetSection("some string"));

builder.Services.AddSingleton<
    IValidateOptions<FirstModelNoNamespace>, FirstValidatorNoNamespace>();
builder.Services.AddSingleton<
    IValidateOptions<SecondModelNoNamespace>, SecondValidatorNoNamespace>();

ValidateOptionsResultBuilder türü

.NET 8, bir ValidateOptionsResult nesnenin oluşturulmasını kolaylaştırmak için türünü tanıtırValidateOptionsResultBuilder. Önemli olan, bu oluşturucu birden çok hatanın birikmesini sağlar. Daha önce, uygulanması IValidateOptions<TOptions>.Validate(String, TOptions) gereken nesneyi oluşturmak ValidateOptionsResult zordu ve bazen katmanlı doğrulama hatalarına neden oldu. Birden çok hata varsa doğrulama işlemi genellikle ilk hatada durdurulur.

Aşağıdaki kod parçacığında örnek kullanımı gösterilmektedir ValidateOptionsResultBuilder.

ValidateOptionsResultBuilder builder = new();
builder.AddError("Error: invalid operation code");
builder.AddResult(ValidateOptionsResult.Fail("Invalid request parameters"));
builder.AddError("Malformed link", "Url");

// Build ValidateOptionsResult object has accumulating multiple errors.
ValidateOptionsResult result = builder.Build();

// Reset the builder to allow using it in new validation operation.
builder.Clear();

LoggerMessageAttribute oluşturucuları

LoggerMessageAttribute artık ek oluşturucu aşırı yüklemeleri sunar. Daha önce parametresiz oluşturucuyu veya tüm parametreleri (olay kimliği, günlük düzeyi ve ileti) gerektiren oluşturucuyu seçmeniz gerekiyordu. Yeni aşırı yüklemeler, gerekli parametreleri azaltılmış kodla belirtme konusunda daha fazla esneklik sunar. Bir olay kimliği sağlamazsanız sistem otomatik olarak bir olay kimliği oluşturur.

public LoggerMessageAttribute(LogLevel level, string message);
public LoggerMessageAttribute(LogLevel level);
public LoggerMessageAttribute(string message);

Uzantı ölçümleri

IMeterFactory arabirimi

Yeni IMeterFactory arabirimi bağımlılık ekleme (DI) kapsayıcılarına kaydedebilir ve nesneleri yalıtılmış bir şekilde oluşturmak Meter için kullanabilirsiniz.

IMeterFactory varsayılan ölçüm fabrikası uygulamasını kullanarak öğesini DI kapsayıcısına kaydedin:

// 'services' is the DI IServiceCollection.
services.AddMetrics();

Tüketiciler daha sonra ölçüm fabrikasını edinebilir ve yeni Meter bir nesne oluşturmak için kullanabilir.

IMeterFactory meterFactory = serviceProvider.GetRequiredService<IMeterFactory>();

MeterOptions options = new MeterOptions("MeterName")
{
    Version = "version",
};

Meter meter = meterFactory.Create(options);

MetricCollector<T> sınıfı

Yeni MetricCollector<T> sınıf, ölçüm ölçümlerini zaman damgalarıyla birlikte kaydetmenizi sağlar. Buna ek olarak, sınıfı doğru zaman damgası oluşturma için seçtiğiniz bir zaman sağlayıcısı kullanma esnekliği sunar.

const string CounterName = "MyCounter";
DateTimeOffset now = DateTimeOffset.Now;

var timeProvider = new FakeTimeProvider(now);
using var meter = new Meter(Guid.NewGuid().ToString());
Counter<long> counter = meter.CreateCounter<long>(CounterName);
using var collector = new MetricCollector<long>(counter, timeProvider);

Assert.IsNull(collector.LastMeasurement);

counter.Add(3);

// Verify the update was recorded.
Assert.AreEqual(counter, collector.Instrument);
Assert.IsNotNull(collector.LastMeasurement);

Assert.AreSame(collector.GetMeasurementSnapshot().Last(), collector.LastMeasurement);
Assert.AreEqual(3, collector.LastMeasurement.Value);
Assert.AreEqual(now, collector.LastMeasurement.Timestamp);

System.Numerics.Tensors.TensorPrimitives

Güncelleştirilmiş System.Numerics.Tensors NuGet paketi, yeni TensorPrimitives ad alanında tensor işlemleri için destek ekleyen API'ler içerir. Tensor ilkelleri, yapay zeka ve makine öğrenmesi gibi yoğun veri kullanan iş yüklerini iyileştirir.

Anlamsal arama ve alma artırılmış oluşturma (RAG) gibi yapay zeka iş yükleri, istemleri ilgili verilerle genişleterek ChatGPT gibi büyük dil modellerinin doğal dil özelliklerini genişletir. Bu iş yükleri için, bir soruyu yanıtlamak için en uygun verileri bulmak için kosinüs benzerliği gibi vektörlerle ilgili işlemler çok önemlidir. System.Numerics.Tensors.TensorPrimitives paketi, vektör işlemleri için API'ler sağlar; başka bir deyişle dış bağımlılık almanız veya kendi uygulamanızı yazmanız gerekmez.

Bu paket System.Numerics.Tensors paketinin yerini alır.

Daha fazla bilgi için Duyuru .NET 8 RC 2 blog gönderisine bakın.

Ayrıca bkz.