deniz.in

Piyasalar

Hava durumu

Hava durumu yükleniyor

· kaynak dev.to (home feed)

.NET 10'da küçük tam sayı türlerinde generic math kaydırmaları artık fazla kaydırmaları sarıyor

.NET 10 artık generic math operatörlerinde kaydırma sayılarını maskeliyor; bu yüzden generic bir byte << 8 ifadesi .NET 9'da 0 döndürürken 1 döndürebiliyor — bit ayrıştırma kodları ve testler için ince bir kırıcı değişiklik.

.NET 10'da küçük tam sayı türlerinde generic math kaydırmaları artık fazla kaydırmaları sarıyor

Ne değişti

.NET 10, küçük tam sayı türlerinde generic math üzerinden yapılan fazla büyük kaydırmaların sonucunu değiştiriyor. dev.to'da yayımlanan bir yazıya göre, IShiftOperators<T, int, T> ile kısıtlanmış generic bir yardımcı, .NET 9'da her zaman sıfır üreten kaydırmalar için artık sıfırdan farklı değerler döndürebiliyor: generic bir byte'ı 8 ile sola kaydırmak .NET 10'da 1 döndürüyor, oysa .NET 9'da 0 döndürüyordu.

Yazı, resmi kırıcı değişiklik notuna atıf yapıyor; nota göre generic kaydırmalar artık kaydırma miktarını, yerleşik tam sayı türlerine uygun şekilde maskeliyor. Etkilenen türler byte, char, sbyte, short ve ushort; etkilenen operatörler ise <<, >> ve unsigned right shift.

Kritik nokta, bunun yalnızca generic math üzerinden çağrılan operatörler için geçerli olması. byteValue << 8 gibi somut bir ifade int'e yükseltilir ve olağan davranışını korur; buna karşılık generic bir metot T döndürür ve yerleşik operatör uygulamasına bağlıdır — değişen şey de tam olarak budur. Bu ayrım, somut türlere karşı yazılan sıradan birim testlerinin yükseltme sırasında kırılmayı yakalayamayabileceğinin nedenidir.

Sınırın yeniden üretilmesi

dev.to örneği net9.0 ve net10.0 için çoklu hedefleme yapıyor ve her iki runtime altında aynı testleri, sayılar tür genişliğine ve bir fazlasına ayarlanmış şekilde çalıştırıyor:

.NET 9: byte-left-8=0, byte-left-9=0 .NET 10: byte-left-8=1, byte-left-9=2

.NET 9: byte-unsigned-right-8=0 .NET 10: byte-unsigned-right-8=128

both: int-left-32-control=1

.NET 10'da, byte için 8'lik kaydırma sayısı 0'a, 9'luk sayı ise 1'e maskeleniyor; dolayısıyla değer sıfırlanmak yerine sıfır veya bir konum kaydırılıyor. int << 32 kontrol vakası her iki runtime'da da 1 döndürüyor, çünkü int zaten kaydırma sayısını maskeliyordu — değişikliğin getirmek istediği tutarlılık da tam olarak budur.

Yazının vurguladığı bir nüans: sayı en büyük geçerli konuma sınırlandırılmıyor (clamp). İşlenenin genişliğine göre indirgeniyor; yani sekiz bitlik bir tür için 8, 16 ve 24 eşdeğer sayılardır. Bu nedenle fazla büyük bir kaydırma, sıfır yerine makul bir sıfır olmayan değer üretebilir ve testler, yeterince büyük bir kaydırmanın tüm bitleri temizlediğini varsaylamak yerine açık bir domaine kuralını doğrulamalıdır.

Yükseltme nasıl denetlenir

Yazar, IShiftOperators, IBinaryInteger, generic kaydırma yardımcıları ve doğrulanmamış bir sayı kabul eden herhangi bir metot için arama yapılmasını, ardından küçük yerleşik türlerin önceliklendirilmesini öneriyor. Tür genişliğinin altındaki derleme zamanı sabiti sayılar etkilenmez; girdiden türetilen sayılar, genişliğe eşit sentinel değerler ve yeniden kullanılabilir bit paketleme yardımcıları çapraz runtime testlerini hak eder. Yalnızca literal byte << desenleri aramak, generic parametrenin nihai işlenen türünü gizlediği durumları gözden kaçıracaktır.

Kaydırma sayısı politikasının açık hale getirilmesi

Yazı, sınırda iki politikadan birinin adlandırılmasını öneriyor. Protokol ofsetleri veya serileştirilmiş bit indeksleri için, count >= width olduğunda ArgumentOutOfRangeException fırlatarak değer genişliği dışındaki sayıları reddedin. Döngüsel sayıların kasıtlı olduğu yerlerde ise count % width ile açıkça normalize edin. Her iki sürüm de genişlik sayısal türle eşleştiğinde .NET 9 ve .NET 10'da aynı sonuçları üretir ve her ikisi de politikayı, runtime'a özgü bir operatör kuralı bilgisi gerektirmeden inceleyenler için görünür kılar. Yazar ayrıca genişliği, ilgisiz bir çağıran değerini kabul etmek yerine sayısal türe bağlı tutmayı öneriyor.

Makale, yalnızca yeni çıktıyı korumak için modulo maskesi eklemeye karşı uyarıyor: fazla büyük bir sayı bozuk girdiyi işaret ediyorsa, maskeleme geçersiz bir değeri makul bir değere dönüştürür. Ayrıştırıcılar, yetkilendirme bit kümeleri, depolama biçimleri ve dışarıdan sağlanan ofsetler için reddetme genellikle daha güvenlidir. Özel sayısal türler kendi operatör sözleşmelerini korur; döndürmeler (rotation), işaret genişletme, negatif sayılar ve kriptografik kodlar ayrı bir inceleme gerektirir. Yazı, .NET 10'un bir LTS sürüm olduğunu belirtiyor ve etkilenen en eski runtime destekten çıkana kadar çapraz hedefli doğrulamaların yerinde tutulmasını öneriyor.

Neden önemli

Bu, generic bir soyutlamanın ardına gizlenmiş dar kapsamlı ama gerçek bir davranış kırılması ve tam olarak somut tür test paketlerinin yakalayamayacağı türden bir değişiklik. Generic math üzerinden bit alanı ayrıştırma, ikili protokol işleme veya kompakt tanımlayıcı paketleme yapan her kod, kaydırma sonuçlarını runtime'lar arasında yeniden doğrulamalı ve kaydırma sayısı politikasını API sınırında açık hale getirmelidir. Runtime artık tam sayı türleri arasında kendi içinde tutarlı; ancak her uygulama, fazla büyük bir sayının geçerli bir girdi mi yoksa bir hata mı olduğuna kendisi karar vermek zorunda.

  • #dotnet
  • #csharp
  • #generic-math
  • #breaking-changes
  • #runtime