Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu makalede .NET 10 için .NET kitaplıklarındaki yeni özellikler açıklanmaktadır.
Şifreleme
- SHA-1 dışındaki parmak izine göre sertifikaları bulma
- ASCII/UTF-8'de PEM ile kodlanmış verileri bulma
- PKCS#12/PFX dışarı aktarma için şifreleme algoritması
- Kuantum sonrası şifreleme (PQC)
SHA-1 dışındaki parmak izine göre sertifikaları bulma
Sertifikaları parmak iziyle benzersiz olarak bulmak oldukça yaygın bir işlemdir, ancak X509Certificate2Collection.Find(X509FindType, Object, Boolean) yöntem (mod için FindByThumbprint ) yalnızca SHA-1 parmak izi değerini arar.
Bu karma algoritmaların uzunlukları aynı olduğundan SHA-2-256 ("SHA256") ve SHA-3-256 parmak izlerini bulmak için Find yöntemini kullanma riski vardır.
Bunun yerine. .NET 10, eşleştirme için kullanılacak karma algoritmasının adını kabul eden yeni bir yöntem tanıtır.
X509Certificate2Collection coll = store.Certificates.FindByThumbprint(HashAlgorithmName.SHA256, thumbprint);
Debug.Assert(coll.Count < 2, "Collection has too many matches, has SHA-2 been broken?");
return coll.SingleOrDefault();
ASCII/UTF-8'de PEM ile kodlanmış verileri bulma
PEM kodlaması (başlangıçta Gizlilik Artırılmış Posta, ancak şimdi e-posta dışında yaygın olarak kullanılır), "metin" için tanımlanır; bu da PemEncoding sınıfının String ve ReadOnlySpan<char>üzerinde çalışacak şekilde tasarlandığı anlamına gelir. Ancak, ASCII (dize) kodlaması kullanan bir dosyada yazılmış bir sertifikaya benzer bir şey olması yaygındır (özellikle Linux'ta). Geçmişte bu, PemEncodingkullanabilmeniz için dosyayı açmanız ve baytları karakterlere (veya dizeye) dönüştürmeniz gerektiği anlamına geliyordu.
Yeni PemEncoding.FindUtf8(ReadOnlySpan<Byte>) yöntem, PEM'in yalnızca 7 bit ASCII karakterleri için tanımlandığı ve bu 7 bit ASCII'nin tek bayt UTF-8 değerleriyle mükemmel bir çakışmaya sahip olması gerçeğinden yararlanır. Bu yeni yöntemi çağırarak UTF-8/ASCII-to-char dönüştürmesini atlayabilir ve dosyayı doğrudan okuyabilirsiniz.
byte[] fileContents = File.ReadAllBytes(path);
-char[] text = Encoding.ASCII.GetString(fileContents);
-PemFields pemFields = PemEncoding.Find(text);
+PemFields pemFields = PemEncoding.FindUtf8(fileContents);
-byte[] contents = Base64.DecodeFromChars(text.AsSpan()[pemFields.Base64Data]);
+byte[] contents = Base64.DecodeFromUtf8(fileContents.AsSpan()[pemFields.Base64Data]);
PKCS#12/PFX dışarı aktarma için şifreleme algoritması
ExportPkcs12 üzerindeki yeni yöntemler, çağıranların çıkışı üretmek için hangi şifreleme ve özet algoritmalarının kullanılacağını seçmesine izin verir.
- Pkcs12ExportPbeParameters.Pkcs12TripleDesSha1 Windows XP dönemine ait de facto standardı gösterir. Eski bir şifreleme algoritması seçerek PKCS#12/PFX okumayı destekleyen hemen her kitaplık ve platform tarafından desteklenen bir çıkış üretir.
- Pkcs12ExportPbeParameters.Pbes2Aes256Sha256 AES'nin 3DES yerine (ve SHA-1 yerine SHA-2-256) kullanılması gerektiğini gösterir, ancak çıkış tüm okuyucular tarafından anlaşılamayabilir (Windows XP gibi).
Daha fazla denetim istiyorsanız, bir kabul eden PbeParameters kullanabilirsiniz.
Kuantum sonrası şifreleme (PQC)
.NET 10 üç yeni asimetrik algoritma için destek içerir: ML-KEM (FIPS 203), ML-DSA (FIPS 204) ve SLH-DSA (FIPS 205). Yeni türler şunlardır:
- System.Security.Cryptography.MLKem
- System.Security.Cryptography.MLDsa
- System.Security.Cryptography.SlhDsa
Çok az fayda sağladığı için bu yeni türler AsymmetricAlgorithm'den türetilmez. Nesne oluşturma ve ardından bir anahtarı içeri aktarma veya yeni bir anahtar oluşturma yaklaşımı yerine AsymmetricAlgorithm , yeni türlerin tümü bir anahtar oluşturmak veya içeri aktarmak için statik yöntemler kullanır:
using System;
using System.IO;
using System.Security.Cryptography;
private static bool ValidateMLDsaSignature(ReadOnlySpan<byte> data, ReadOnlySpan<byte> signature, string publicKeyPath)
{
string publicKeyPem = File.ReadAllText(publicKeyPath);
using (MLDsa key = MLDsa.ImportFromPem(publicKeyPem))
{
return key.VerifyData(data, signature);
}
}
Nesne özelliklerini ayarlayıp bir anahtarın ortaya çıkmasını sağlamak yerine, bu yeni türlerde anahtar üretimi, ihtiyaç duyduğu tüm seçenekleri alır.
using (MLKem key = MLKem.GenerateKey(MLKemAlgorithm.MLKem768))
{
string publicKeyPem = key.ExportSubjectPublicKeyInfoPem();
...
}
Bu algoritmaların tümü, algoritmanın geçerli sistemde desteklenip desteklenmediğini belirtmek için statik IsSupported bir özelliğe sahip olma deseniyle devam eder.
.NET 10, Windows Şifreleme API'sini içerir: Kuantum Sonrası Şifreleme (PQC) için Yeni Nesil (CNG) desteği, bu algoritmaları PQC desteğine sahip Windows sistemlerinde kullanılabilir hale getirir. Örneğin:
using System;
using System.IO;
using System.Security.Cryptography;
private static bool ValidateMLDsaSignature(ReadOnlySpan<byte> data, ReadOnlySpan<byte> signature, string publicKeyPath)
{
string publicKeyPem = File.ReadAllText(publicKeyPath);
using MLDsa key = MLDsa.ImportFromPem(publicKeyPem);
return key.VerifyData(data, signature);
}
PQC algoritmaları, sistem şifreleme kitaplıklarının OpenSSL 3.5 (veya daha yeni) veya PQC desteğine sahip Windows CNG olduğu sistemlerde kullanılabilir. Tür MLKem olarak [Experimental] işaretlenmemiştir, ancak bazı metotları işaretlenmiştir (ve böyle kalacaktır, ta ki temel alınan standartlar sonlanana kadar). Geliştirme tamamlanana kadar MLDsa, SlhDsa ve CompositeMLDsa sınıfları tanılama altında [Experimental] olarak SYSLIB5006 ile işaretlenmiştir.
ML-DSA
sınıfı, MLDsa yaygın kod desenlerini basitleştiren kullanım kolaylığı özellikleri içerir:
private static byte[] SignData(string privateKeyPath, ReadOnlySpan<byte> data)
{
using (MLDsa signingKey = MLDsa.ImportFromPem(File.ReadAllBytes(privateKeyPath)))
{
- byte[] signature = new byte[signingKey.Algorithm.SignatureSizeInBytes];
- signingKey.SignData(data, signature);
+ return signingKey.SignData(data);
- return signature;
}
}
Buna ek olarak, .NET 10 bunu "saf" ML-DSA'dan ayırt etmeye yardımcı olmak için "PreHash" olarak adlandırılan HashML-DSA desteği ekler. Temel belirtim Nesne Tanımlayıcısı (OID) değeriyle etkileşime geçerken, bu [Experimental] türdeki SignPreHash ve VerifyPreHash yöntemleri noktalı ondalık OID'yi dize olarak alır. Bu, HashML-DSA kullanan daha fazla senaryo iyi tanımlandığında gelişebilir.
private static byte[] SignPreHashSha3_256(MLDsa signingKey, ReadOnlySpan<byte> data)
{
const string Sha3_256Oid = "2.16.840.1.101.3.4.2.8";
return signingKey.SignPreHash(SHA3_256.HashData(data), Sha3_256Oid);
}
RC 1'den başlayarak, ML-DSA gelişmiş şifreleme senaryoları için ek esneklik sağlayan "dış" mu değerinden oluşturulan ve doğrulanan imzaları da destekler:
private static byte[] SignWithExternalMu(MLDsa signingKey, ReadOnlySpan<byte> externalMu)
{
return signingKey.SignMu(externalMu);
}
private static bool VerifyWithExternalMu(MLDsa verifyingKey, ReadOnlySpan<byte> externalMu, ReadOnlySpan<byte> signature)
{
return verifyingKey.VerifyMu(externalMu, signature);
}
Bileşik ML-DSA
.NET 10, ietf-lamps-pq-composite-sigs (.NET 10 GA itibarıyla taslak 8'de), ve CompositeMLDsa türleri dahil olmak üzere CompositeMLDsaAlgorithm RSA varyantları için temel yöntemlerin uygulanmasıyla birlikte yeni türler sunar.
var algorithm = CompositeMLDsaAlgorithm.MLDsa65WithRSA4096Pss;
using var privateKey = CompositeMLDsa.GenerateKey(algorithm);
byte[] data = [42];
byte[] signature = privateKey.SignData(data);
using var publicKey = CompositeMLDsa.ImportCompositeMLDsaPublicKey(algorithm, privateKey.ExportCompositeMLDsaPublicKey());
Console.WriteLine(publicKey.VerifyData(data, signature)); // True
signature[0] ^= 1; // Tamper with signature
Console.WriteLine(publicKey.VerifyData(data, signature)); // False
Doldurmalı AES KeyWrap (IETF RFC 5649)
AES-KWP, içeriğin bir kez şifrelendiği ancak şifre çözme anahtarının her biri ayrı bir gizli formda olmak üzere birden çok tarafa dağıtılması gereken Şifreleme İletiSi Sözdizimi (CMS) EnvelopedData gibi yapılarda zaman zaman kullanılan bir algoritmadır.
.NET artık sınıfındaki örnek yöntemleri aracılığıyla AES-KWP algoritmasını Aes destekliyor:
private static byte[] DecryptContent(ReadOnlySpan<byte> kek, ReadOnlySpan<byte> encryptedKey, ReadOnlySpan<byte> ciphertext)
{
using (Aes aes = Aes.Create())
{
aes.SetKey(kek);
Span<byte> dek = stackalloc byte[256 / 8];
int length = aes.DecryptKeyWrapPadded(encryptedKey, dek);
aes.SetKey(dek.Slice(0, length));
return aes.DecryptCbc(ciphertext);
}
}
Genelleştirme ve tarih/saat
- DateOnly türü için ISOWeek'te yöntemlerin yeni aşırı yüklenmesi
- Dize karşılaştırması için sayısal sıralama
-
Tek parametreli yeni
TimeSpan.FromMillisecondsaşırı yükleme
DateOnly türü için ISOWeek'te yeni yöntem aşırı yüklemeleri
ISOWeek sınıfı başlangıçta DateTime türü mevcut olmadan önce tanıtıldığı gibi yalnızca DateOnlyile çalışacak şekilde tasarlanmıştır. artık DateOnly kullanıma sunulduğuna göre, ISOWeek de bunu desteklemesi mantıklıdır. Aşağıdaki aşırı yüklemeler yenidir:
Dize karşılaştırması için sayısal sıralama
Sayısal dize karşılaştırması, dizeleri sözcük bilimi yerine sayısal olarak karşılaştırmak için yüksek düzeyde istenen bir özelliktir. Örneğin, 210'den küçük olduğundan, sayısal olarak sıralandığında "2" önce "10" görünmelidir. Benzer şekilde, "2" ve "02" sayısal olarak eşittir. Yeni NumericOrdering seçenekle, artık şu tür karşılaştırmalar yapmak mümkündür:
StringComparer numericStringComparer = StringComparer.Create(CultureInfo.CurrentCulture, CompareOptions.NumericOrdering);
Console.WriteLine(numericStringComparer.Equals("02", "2"));
// Output: True
foreach (string os in new[] { "Windows 8", "Windows 10", "Windows 11" }.Order(numericStringComparer))
{
Console.WriteLine(os);
}
// Output:
// Windows 8
// Windows 10
// Windows 11
HashSet<string> set = new HashSet<string>(numericStringComparer) { "007" };
Console.WriteLine(set.Contains("7"));
// Output: True
Bu seçenek şu dizin tabanlı dize işlemleri için geçerli değildir: IndexOf, LastIndexOf, StartsWith, EndsWith, IsPrefixve IsSuffix.
Tek parametreli yeni TimeSpan.FromMilliseconds aşırı yükleme
TimeSpan.FromMilliseconds(Int64, Int64) yöntemi daha önce tek bir parametre alan bir aşırı yükleme eklemeden tanıtılmıştı.
İkinci parametre isteğe bağlı olduğundan bu işe yarasa da, aşağıdaki gibi bir LINQ ifadesinde kullanıldığında derleme hatasına neden olur:
Expression<Action> a = () => TimeSpan.FromMilliseconds(1000);
LINQ ifadeleri isteğe bağlı parametreleri işleyemediğinden bu sorun ortaya çıkar. Bu sorunu çözmek için, .NET 10 tek bir parametre alan yeni bir aşırı yükleme tanıtır. Ayrıca ikinci parametreyi zorunlu hale getirmek için mevcut yöntemi değiştirir.
Dize
- Karakter aralığıyla çalışmak için dize normalleştirme API'leri
- Hex-dizi dönüştürme için UTF-8 desteği
Karakter aralığıyla çalışmak için dize normalleştirme API'leri
Unicode dize normalleştirmesi uzun süredir destekleniyor, ancak var olan API'ler yalnızca dize türüyle çalıştı. Bu, karakter dizileri veya yayılma alanları gibi farklı biçimlerde depolanan verileri olan çağıranların bu API'leri kullanmak için yeni bir dize ayırması gerektiği anlamına gelir. Ayrıca, normalleştirilmiş bir dize döndüren API'ler her zaman normalleştirilmiş çıkışı temsil etmek için yeni bir dize ayırır.
.NET 10, dize türlerinin ötesinde normalleştirmeyi genişleten ve gereksiz ayırmaları önlemeye yardımcı olan karakter aralıklarıyla çalışan yeni API'ler ekler:
- StringNormalizationExtensions.GetNormalizedLength(ReadOnlySpan<Char>, NormalizationForm)
- StringNormalizationExtensions.IsNormalized(ReadOnlySpan<Char>, NormalizationForm)
- StringNormalizationExtensions.TryNormalize(ReadOnlySpan<Char>, Span<Char>, Int32, NormalizationForm)
Onaltılık dize dönüştürme için UTF-8 desteği
UTF-8 desteği, .NET 10 uygulamasında hex-string dönüşüm işlemleri için Convert sınıfına eklenir. Bu yeni yöntemler, ara dize tahsislerine gerek kalmadan UTF-8 bayt dizileri ile onaltılık gösterimler arasında dönüştürmenin verimli yollarını sunar.
- Convert.FromHexString(ReadOnlySpan<Byte>)
- Convert.FromHexString(ReadOnlySpan<Byte>, Span<Byte>, Int32, Int32)
- Convert.TryToHexString(ReadOnlySpan<Byte>, Span<Byte>, Int32)
- Convert.TryToHexStringLower(ReadOnlySpan<Byte>, Span<Byte>, Int32)
Bu yöntemler, string ile çalışan mevcut aşırı yüklemeleri yansıtır, ancak zaten UTF-8 kodlamalı baytlarla çalıştığınız senaryolarda iyileştirilmiş performans için doğrudan UTF-8 kodlamalı baytlar üzerinde çalışır.
Koleksiyonlar
TryAdd için ilave TryGetValue ve OrderedDictionary<TKey, TValue> yükleri
OrderedDictionary<TKey,TValue>, diğer TryAdd uygulamaları gibi ekleme ve alma için TryGetValue ve IDictionary<TKey, TValue> sağlar. Ancak, daha fazla işlem gerçekleştirmek isteyebileceğiniz senaryolar vardır, bu nedenle girişe bir dizin döndüren yeni aşırı yüklemeler eklenir:
Bu dizin, girişe hızlı erişim sağlamak için GetAt ve SetAt ile kullanılabilir. Yeni TryAdd aşırı yüklemenin örnek kullanımlarından biri, sıralı sözlükte bir anahtar-değer çifti eklemek veya güncelleştirmektir:
// Try to add a new key with value 1.
if (!orderedDictionary.TryAdd(key, 1, out int index))
{
// Key was present, so increment the existing value instead.
int value = orderedDictionary.GetAt(index).Value;
orderedDictionary.SetAt(index, value + 1);
}
Bu yeni API zaten JsonObject'de kullanılıyor ve özellikleri güncelleme performansını %10-20%oranında artırıyor.
Seri -leştirme
-
içinde ReferenceHandler belirtmeye izin ver
JsonSourceGenerationOptions - Yinelenen JSON özelliklerine izin vermeme seçeneği
- Katı JSON serileştirme seçenekleri
- JSON seri hale getiricisi için PipeReader desteği
JsonSourceGenerationOptions'de ReferenceHandler belirtmeye izin ver
JSON serileştirmesi için kaynak oluşturucuları kullandığınızda, döngüler seri hale getirildiğinde veya seri durumdan çıkarıldığında, oluşturulan bağlam bir hata fırlatır. Artık ReferenceHandler içinde JsonSourceGenerationOptionsAttribute öğesini belirterek bu davranışı özelleştirebilirsiniz. aşağıda JsonKnownReferenceHandler.Preservekullanan bir örnek verilmişti:
public static void MakeSelfRef()
{
SelfReference selfRef = new SelfReference();
selfRef.Me = selfRef;
Console.WriteLine(JsonSerializer.Serialize(selfRef, ContextWithPreserveReference.Default.SelfReference));
// Output: {"$id":"1","Me":{"$ref":"1"}}
}
[JsonSourceGenerationOptions(ReferenceHandler = JsonKnownReferenceHandler.Preserve)]
[JsonSerializable(typeof(SelfReference))]
internal partial class ContextWithPreserveReference : JsonSerializerContext
{
}
internal class SelfReference
{
public SelfReference Me { get; set; } = null!;
}
Yinelenen JSON özelliklerini yasaklama seçeneği
JSON belirtimi, bir JSON yükünü seri durumdan çıkarırken yinelenen özelliklerin nasıl işleneceğini belirtmez. Bu, beklenmeyen sonuçlara ve güvenlik açıklarına yol açabilir. .NET 10, yinelenen JSON özelliklerine izin vermeme seçeneğini tanıtır JsonSerializerOptions.AllowDuplicateProperties:
string json = """{ "Value": 1, "Value": -1 }""";
Console.WriteLine(JsonSerializer.Deserialize<MyRecord>(json).Value); // -1
JsonSerializerOptions options = new() { AllowDuplicateProperties = false };
JsonSerializer.Deserialize<MyRecord>(json, options); // throws JsonException
JsonSerializer.Deserialize<JsonObject>(json, options); // throws JsonException
JsonSerializer.Deserialize<Dictionary<string, int>>(json, options); // throws JsonException
JsonDocumentOptions docOptions = new() { AllowDuplicateProperties = false };
JsonDocument.Parse(json, docOptions); // throws JsonException
record MyRecord(int Value);
Seri durumdan çıkarma sırasında bir değerin birden fazla kez atanıp atanmadığı kontrol edilerek yinelemeler tespit edilir; bu nedenle büyük/küçük harf duyarlılığı ve adlandırma ilkesi gibi diğer seçeneklerle beklendiği gibi çalışır.
Katı JSON serileştirme seçenekleri
JSON serileştirici, serileştirme ve seri durumdan çıkarma işlemlerini özelleştirmek için birçok seçenek kabul eder, ancak varsayılan ayarlar bazı uygulamalar için çok esnek olabilir. .NET 10, aşağıdaki seçenekleri ekleyerek en iyi yöntemleri izleyen yeni JsonSerializerOptions.Strict bir ön ayar ekler:
- İlkeyi JsonUnmappedMemberHandling.Disallow uygular.
- devre dışı bırak JsonSerializerOptions.AllowDuplicateProperties.
- Büyük/küçük harfe duyarlı özellik bağlamasını korur.
- JsonSerializerOptions.RespectNullableAnnotations ve JsonSerializerOptions.RespectRequiredConstructorParameters ayarlarını etkinleştirir.
Bu seçenekler, JsonSerializerOptions.Default ile okuma uyumludur - JsonSerializerOptions.Default ile serileştirilmiş bir nesne, JsonSerializerOptions.Strict ile seri durumdan çıkarılabilir.
JSON serileştirmesi hakkında daha fazla bilgi için bkz . System.Text.Json'a genel bakış.
JSON seri hale getiricisi için PipeReader desteği
JsonSerializer.Deserialize
PipeReaderartık mevcut PipeWriter desteği tamamlayarak destekler. Daha önce, gerekli bir PipeReader seri durumdan çıkarılarak bir öğesine dönüştürülüyor Streamancak yeni aşırı yüklemeler doğrudan seri hale getiriciye tümleştirerek PipeReader bu adımı ortadan kaldırıyor. Bir bonus olarak, elinizdekilerden dönüştürmek zorunda kalmak bazı verimlilik avantajları sağlayabilir.
Bu, temel kullanımı gösterir:
using System;
using System.IO.Pipelines;
using System.Text.Json;
using System.Threading.Tasks;
var pipe = new Pipe();
// Serialize to writer
await JsonSerializer.SerializeAsync(pipe.Writer, new Person("Alice"));
await pipe.Writer.CompleteAsync();
// Deserialize from reader
var result = await JsonSerializer.DeserializeAsync<Person>(pipe.Reader);
await pipe.Reader.CompleteAsync();
Console.WriteLine($"Your name is {result.Name}.");
// Output: Your name is Alice.
record Person(string Name);
Öbekler halinde belirteçler üreten bir üretici ve bunları alan ve görüntüleyen bir tüketici örneği aşağıda verilmiştir:
using System;
using System.Collections.Generic;
using System.IO.Pipelines;
using System.Text.Json;
using System.Threading.Tasks;
var pipe = new Pipe();
// Producer writes to the pipe in chunks.
var producerTask = Task.Run(async () =>
{
async static IAsyncEnumerable<Chunk> GenerateResponse()
{
yield return new Chunk("The quick brown fox", DateTime.Now);
await Task.Delay(500);
yield return new Chunk(" jumps over", DateTime.Now);
await Task.Delay(500);
yield return new Chunk(" the lazy dog.", DateTime.Now);
}
await JsonSerializer.SerializeAsync<IAsyncEnumerable<Chunk>>(pipe.Writer, GenerateResponse());
await pipe.Writer.CompleteAsync();
});
// Consumer reads from the pipe and outputs to console.
var consumerTask = Task.Run(async () =>
{
var thinkingString = "...";
var clearThinkingString = new string("\b\b\b");
var lastTimestamp = DateTime.MinValue;
// Read response to end.
Console.Write(thinkingString);
await foreach (var chunk in JsonSerializer.DeserializeAsyncEnumerable<Chunk>(pipe.Reader))
{
Console.Write(clearThinkingString);
Console.Write(chunk.Message);
Console.Write(thinkingString);
lastTimestamp = DateTime.Now;
}
Console.Write(clearThinkingString);
Console.WriteLine($" Last message sent at {lastTimestamp}.");
await pipe.Reader.CompleteAsync();
});
await producerTask;
await consumerTask;
record Chunk(string Message, DateTime Timestamp);
Bunların tümü JSON Pipe olarak seri hale getirilir (okunabilirlik için burada biçimlendirilir):
[
{
"Message": "The quick brown fox",
"Timestamp": "2025-08-01T18:37:27.2930151-07:00"
},
{
"Message": " jumps over",
"Timestamp": "2025-08-01T18:37:27.8594502-07:00"
},
{
"Message": " the lazy dog.",
"Timestamp": "2025-08-01T18:37:28.3753669-07:00"
}
]
Sistem.Sayılar
Diğer sol elle kullanılan matris dönüştürme yöntemleri
.NET 10, pano ve kısıtlanmış billboard matrisleri için sol elle dönüştürme matrisleri oluşturmak için kalan API'leri ekler. Bunun yerine bir sol elle koordinat sistemi kullanırken, mevcut sağ elle kullanılan karşılıkları CreateBillboard(Vector3, Vector3, Vector3, Vector3)gibi bu yöntemleri kullanabilirsiniz:
- Matrix4x4.CreateBillboardLeftHanded(Vector3, Vector3, Vector3, Vector3)
- Matrix4x4.CreateConstrainedBillboardLeftHanded(Vector3, Vector3, Vector3, Vector3, Vector3)
Tensor geliştirmeleri
System.Numerics.Tensors alanı artık Lengths ve Strides gibi işlemleri gerçekleştirmek için, IReadOnlyTensor adı verilen genel olmayan bir arabirim içerir. Dilim işlemleri artık verileri kopyalamaz ve bu da performansı artırır. Buna ek olarak, performans kritik olmadığında verileri genel olmayan bir şekilde object ile kutulama yaparak erişebilirsiniz.
Tensor API'leri artık kararlıdır ve artık deneysel olarak işaretlenmemektedir. API'ler hala System.Numerics.Tensors NuGet paketine başvurmayı gerektirse de, .NET 10 sürümü için kapsamlı bir şekilde gözden geçirilmiş ve sonlandırılmıştır. Türler, temel alınan tür T işlemi desteklediğinde aritmetik işlemler sağlamak için C# 14 uzantı işleçlerinden yararlanir. Eğer T ilgili genel matematik arabirimlerini, örneğin IAdditionOperators<TSelf, TOther, TResult> veya INumber<TSelf>, uygularsa işlem desteklenir. Örneğin, tensor + tensor için Tensor<int> kullanılabilir, ancak Tensor<bool> için mevcut değil.
Seçenekler doğrulaması
ValidationContext için yeni AOT güvenli oluşturucu
Seçenek doğrulaması sırasında kullanılan ValidationContext sınıfı, displayName parametresini açıkça kabul eden yeni bir oluşturucu aşırı yüklemesi içerir.
ValidationContext(Object, String, IServiceProvider, IDictionary<Object,Object>)
Görünen ad, AOT güvenliğini sağlar ve uyarı olmadan yerel derlemelerde kullanılmasını sağlar.
Tanılama
-
telemetri şeması URL'leri için
ActivitySourceveMeterdesteği - Etkinlik olayları ve bağlantıları için süreç dışı izleme desteği
- Hız sınırlama iz örnekleme desteği
ActivitySource ve Meter içindeki telemetri şeması URL'leri için destek
ActivitySource ve Meter şimdi oluşturma sırasında OpenTelemetry belirtimleriyle uyumlu bir telemetri şeması URL'si belirtmeyi destekliyor. Telemetri şeması, izleme ve ölçüm verileri için tutarlılık ve uyumluluk sağlar. Ayrıca, .NET 10, birden çok yapılandırma seçeneği (ActivitySourceOptions dahil) ile ActivitySource örneklerinin oluşturulmasını basitleştiren öğesini tanıtır.
Yeni API'ler şunlardır:
- ActivitySource(ActivitySourceOptions)
- ActivitySource.TelemetrySchemaUrl
- Meter.TelemetrySchemaUrl
- ActivitySourceOptions
Etkinlik olayları ve bağlantıları için kullanıma hazır izleme desteği
sınıfı, Activity hizmetler veya bileşenler arasında işlem akışını izleyerek dağıtılmış izlemeyi etkinleştirir. .NET, olay kaynağı sağlayıcısı aracılığıyla bu izleme verilerini işlem dışı olarak serileştirmeyi Microsoft-Diagnostics-DiagnosticSource destekler. Bir Activity, ActivityLink ve ActivityEvent gibi ek meta veriler içerebilir. .NET 10, bu bağlantıları ve olayları seri hale getirme desteğini ekler, dolayısıyla dış işlem izleme verileri artık bu bilgileri içerir. Örneğin:
Events->"[(TestEvent1,2025-03-27T23:34:10.6225721+00:00,[E11:EV1,E12:EV2]),(TestEvent2,2025-03-27T23:34:11.6276895+00:00,[E21:EV21,E22:EV22])]"
Links->"[(19b6e8ea216cb2ba36dd5d957e126d9f,98f7abcb3418f217,Recorded,null,false,[alk1:alv1,alk2:alv2]),(2d409549aadfdbdf5d1892584a5f2ab2,4f3526086a350f50,None,null,false)]"
Hız sınırı izleme örnekleme desteği
Dağıtılmış izleme verileri olay kaynağı sağlayıcısı aracılığıyla Microsoft-Diagnostics-DiagnosticSource işlem dışı olarak seri hale getirildiğinde, kaydedilen tüm etkinlikler yayılabilir veya izleme oranına göre örnekleme uygulanabilir.
Hız Sınırlama Örneklemesi adlı yeni örnekleme seçeneği, saniye başına seri hale getirilen kök etkinliklerin sayısını kısıtlar. Bu, veri hacmini daha hassas bir şekilde denetlemeye yardımcı olur.
Harici işlem izleme veri toplayıcıları, FilterAndPayloadSpecs seçeneğini belirterek bu örneklemeyi etkinleştirebilir ve yapılandırabilir. Örneğin, aşağıdaki ayar serileştirmeyi tüm ActivitySource örneklerde saniyede 100 kök etkinlikle sınırlar:
[AS]*/-ParentRateLimitingSampler(100)
ZIP dosyaları
- ZipArchive performansı ve bellek geliştirmeleri
- Yeni zaman uyumsuz ZIP API'leri
- Birleştirilmiş akışlar için GZipStream'de performans iyileştirmesi
ZipArchive performansı ve bellek geliştirmeleri
.NET 10, ZipArchiveperformansını ve bellek kullanımını geliştirir.
İlk olarak, ZipArchive modunda bir Update'a girişlerin yazılma şekli optimize edildi. Daha önce tüm ZipArchiveEntry örnekleri belleğe yüklenip yeniden yazılıyordu ve bu da yüksek bellek kullanımı ve performans sorunlarına yol açabiliyordu. İyileştirme, bellek kullanımını azaltır ve tüm girişleri belleğe yükleme gereksinimini ortadan kaldırarak performansı artırır.
İkincisi, ZipArchive girdilerinin ayıkılması artık paralelleştirilmiştir ve iç veri yapıları daha iyi bellek kullanımı için iyileştirilmiştir. Bu geliştirmeler performans sorunları ve yüksek bellek kullanımıyla ilgili sorunları ele alır ve özellikle büyük arşivlerle ilgilenirken ZipArchive daha verimli ve hızlı hale getirir.
Yeni zaman uyumsuz ZIP API'leri
.NET 10, ZIP dosyalarından okurken veya zip dosyalarına yazarken engellemeyen işlemler gerçekleştirmeyi kolaylaştıran yeni zaman uyumsuz API'ler getirir. Bu özellik topluluk tarafından yüksek oranda istendi.
ZIP arşivlerini ayıklamak, oluşturmak ve güncelleştirmek için yeni async yöntemler kullanılabilir. Bu yöntemler, geliştiricilerin özellikle G/Ç ile ilişkili işlemleri içeren senaryolarda büyük dosyaları verimli bir şekilde işlemesine ve uygulama yanıt hızını iyileştirmesine olanak tanır. Bu yöntemler şunlardır:
- ZipArchive.CreateAsync(Stream, ZipArchiveMode, Boolean, Encoding, CancellationToken)
- ZipArchiveEntry.OpenAsync(CancellationToken)
- ZipFile.CreateFromDirectoryAsync
- ZipFile.ExtractToDirectoryAsync
- ZipFile.OpenAsync
- ZipFile.OpenReadAsync(String, CancellationToken)
- ZipFileExtensions.CreateEntryFromFileAsync
- ZipFileExtensions.ExtractToDirectoryAsync
- ZipFileExtensions.ExtractToFileAsync
Bu API'leri kullanma örnekleri için Önizleme 4 blog gönderisine bakın.
Birleştirilmiş akışlar için GZipStream'de performans iyileştirmesi
Topluluk katkısı, birleştirilmiş GZip veri akışlarını işlerken GZipStream performansını geliştirdi. Daha önce, her yeni akış kesimi iç ZLibStreamHandle öğesini atar ve yeniden tahsis ederdi, bu da ek bellek ayırmaları ve başlatma ek yüküne neden olurdu. Bu değişiklikle, tutacak artık hem yönetilen hem de yönetilmeyen bellek ayırmalarını azaltmak ve çalışma süresini iyileştirmek için sıfırlanıp yeniden kullanılır. Çok sayıda küçük veri akışı işlenirken en büyük etki (yaklaşık 35% daha hızlı) görülür. Bu değişiklik:
- Birleştirilmiş her akış için yaklaşık 64-80 bayt bellek ayırmayı ortadan kaldırır ve yönetilmeyen bellek tasarrufları sağlar.
- Yürütme süresini birleştirilmiş akış başına yaklaşık 400 ns azaltır.
Windows işlem yönetimi
Yeni işlem grubunda Windows işlemlerini başlatma
Windows için artık ayrı bir işlem grubunda işlem başlatmak için kullanabilirsiniz ProcessStartInfo.CreateNewProcessGroup . Bu, alt işlemlere düzgün işleme olmadan ebeveyni indirebilecek yalıtılmış sinyaller göndermenizi sağlar. Sinyal göndermek, zorunlu sonlandırmayı önlemek için uygundur.
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
class Program
{
static void Main(string[] args)
{
bool isChildProcess = args.Length > 0 && args[0] == "child";
if (!isChildProcess)
{
var psi = new ProcessStartInfo
{
FileName = Environment.ProcessPath,
Arguments = "child",
CreateNewProcessGroup = true,
};
using Process process = Process.Start(psi)!;
Thread.Sleep(5_000);
GenerateConsoleCtrlEvent(CTRL_C_EVENT, (uint)process.Id);
process.WaitForExit();
Console.WriteLine("Child process terminated gracefully, continue with the parent process logic if needed.");
}
else
{
// If you need to send a CTRL+C, the child process needs to re-enable CTRL+C handling, if you own the code, you can call SetConsoleCtrlHandler(NULL, FALSE).
// see https://learn.microsoft.com/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw#remarks
SetConsoleCtrlHandler((IntPtr)null, false);
Console.WriteLine("Greetings from the child process! I need to be gracefully terminated, send me a signal!");
bool stop = false;
var registration = PosixSignalRegistration.Create(PosixSignal.SIGINT, ctx =>
{
stop = true;
ctx.Cancel = true;
Console.WriteLine("Received CTRL+C, stopping...");
});
StreamWriter sw = File.AppendText("log.txt");
int i = 0;
while (!stop)
{
Thread.Sleep(1000);
sw.WriteLine($"{++i}");
Console.WriteLine($"Logging {i}...");
}
// Clean up
sw.Dispose();
registration.Dispose();
Console.WriteLine("Thanks for not killing me!");
}
}
private const int CTRL_C_EVENT = 0;
private const int CTRL_BREAK_EVENT = 1;
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetConsoleCtrlHandler(IntPtr handler, [MarshalAs(UnmanagedType.Bool)] bool Add);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GenerateConsoleCtrlEvent(uint dwCtrlEvent, uint dwProcessGroupId);
}
WebSocket geliştirmeleri
WebSocketStream
.NET 10, .NET'teki en yaygın ve daha önce zahmetliWebSocketStream senaryolardan bazılarını basitleştirmek için tasarlanmış yeni bir API'yi kullanıma sunarWebSocket.
Geleneksel WebSocket API'ler düşük düzeydedir ve önemli bir ortak yapı gerektirir: arabelleğe alma ve çerçeveleme, iletileri yeniden oluşturma, kodlama/kod çözme işlemlerini yönetme ve akışlar, kanallar veya diğer aktarım soyutlamalarıyla tümleştirmek için özel sarmalayıcılar yazma. Bu karmaşıklıklar, özellikle akış veya metin tabanlı protokollere sahip uygulamalar ya da olay temelli işleyiciler için WebSockets'in aktarım olarak kullanılmasını zor hale getirir.
WebSocketStream Bir WebSocket üzerinden tabanlı bir Streamsoyutlama sağlayarak bu ağrı noktalarını giderir. Bu, ikili veya metin olsun, verileri okumak, yazmak ve ayrıştırmak için mevcut API'lerle sorunsuz tümleştirme sağlar ve el ile tesisat ihtiyacını azaltır.
WebSocketStream yaygın WebSocket tüketimi ve üretim desenleri için üst düzey, tanıdık API'leri etkinleştirir. Bu API'ler sürtünmeyi azaltır ve gelişmiş senaryoların uygulanmasını kolaylaştırır.
Yaygın kullanım desenleri
Tipik iş akışlarının WebSocketStream nasıl WebSocket basitleştirildiğinden birkaç örnek aşağıda verilmiştir:
Akış metin protokolü (örneğin, STOMP)
using System.IO;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
// Streaming text protocol (for example, STOMP).
using Stream transportStream = WebSocketStream.Create(
connectedWebSocket,
WebSocketMessageType.Text,
ownsWebSocket: true);
// Integration with Stream-based APIs.
// Don't close the stream, as it's also used for writing.
using var transportReader = new StreamReader(transportStream, leaveOpen: true);
var line = await transportReader.ReadLineAsync(cancellationToken); // Automatic UTF-8 and new line handling.
transportStream.Dispose(); // Automatic closing handshake handling on `Dispose`.
akış ikili protokolü (örneğin, AMQP)
using System;
using System.IO;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
// Streaming binary protocol (for example, AMQP).
Stream transportStream = WebSocketStream.Create(
connectedWebSocket,
WebSocketMessageType.Binary,
closeTimeout: TimeSpan.FromSeconds(10));
await message.SerializeToStreamAsync(transportStream, cancellationToken);
var receivePayload = new byte[payloadLength];
await transportStream.ReadExactlyAsync(receivePayload, cancellationToken);
transportStream.Dispose();
// `Dispose` automatically handles closing handshake.
Tek bir iletiyi akış olarak okuma (örneğin, JSON seri durumdan çıkarma)
using System.IO;
using System.Net.WebSockets;
using System.Text.Json;
// Reading a single message as a stream (for example, JSON deserialization).
using Stream messageStream = WebSocketStream.CreateReadableMessageStream(connectedWebSocket, WebSocketMessageType.Text);
// JsonSerializer.DeserializeAsync reads until the end of stream.
var appMessage = await JsonSerializer.DeserializeAsync<AppMessage>(messageStream);
Akış olarak tek bir ileti yazma (örneğin, ikili serileştirme)
using System;
using System.IO;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
// Writing a single message as a stream (for example, binary serialization).
public async Task SendMessageAsync(AppMessage message, CancellationToken cancellationToken)
{
using Stream messageStream = WebSocketStream.CreateWritableMessageStream(_connectedWebSocket, WebSocketMessageType.Binary);
foreach (ReadOnlyMemory<byte> chunk in message.SplitToChunks())
{
await messageStream.WriteAsync(chunk, cancellationToken);
}
} // EOM sent on messageStream.Dispose().
TLS geliştirmeleri
macOS için TLS 1.3 (istemci)
.NET 10, Apple'ın Network.framework'lerini SslStream ve HttpClientile tümleştirerek macOS üzerinde istemci tarafı TLS 1.3 desteği ekler. Geçmişte, macOS TLS 1.3'i desteklemeyen Güvenli Aktarım'ı kullanıyordu; Network.framework'e katılmanız TLS 1.3'e olanak tanır.
Kapsam ve davranış
- yalnızca macOS, bu sürümde istemci tarafı.
- Kabul et. Mevcut uygulamalar etkin olmadığı sürece geçerli yığını kullanmaya devam ediyor.
- Etkinleştirildiğinde, eski TLS sürümleri (TLS 1.0 ve 1.1) artık Network.framework üzerinden kullanılamayabilir.
Nasıl Etkinleştirilir
Kodda AppContext anahtarı kullanın:
// Opt in to Network.framework-backed TLS on Apple platforms.
AppContext.SetSwitch("System.Net.Security.UseNetworkFramework", true);
using var client = new HttpClient();
var html = await client.GetStringAsync("https://example.com");
Veya bir ortam değişkeni kullanın:
# Opt-in via environment variable (set for the process or machine as appropriate)
DOTNET_SYSTEM_NET_SECURITY_USENETWORKFRAMEWORK=1
# or
DOTNET_SYSTEM_NET_SECURITY_USENETWORKFRAMEWORK=true
Notes
- TLS 1.3, üzerinde oluşturulan ve API'ler için SslStream geçerlidir (örneğin,HttpClient/HttpMessageHandler ).
- Şifre paketleri, macOS tarafından Network.framework üzerinden denetleniyor.
- Network.framework etkinleştirildiğinde temel alınan akış davranışı farklılık gösterebilir (örneğin arabelleğe alma, okuma/yazma tamamlama, iptal semantiği).
- Semantik sıfır bayt okumaları için farklılık gösterebilir. Veri kullanılabilirliğini algılamak için sıfır uzunluklu okumalara güvenmekten kaçının.
- Bazı uluslararası etki alanı adları (IDN) ana bilgisayar adları Network.framework tarafından reddedilebilir. ASCII/Punycode (A-label) konak adlarını tercih edin veya macOS/Network.framework kısıtlamalarına karşı adları doğrulayın.
- Uygulamanız belirli SslStream bir edge-case davranışına bağlıysa, Network.framework altında doğrulayın.