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.
.NET 11'de, byte, short, ushort, char ve sbyte türlerine yapılan denetimsiz kayan noktalı dönüşümler artık hedef türün sınır değerlerinde doyumlu davranış sergiler. Çok küçük veya çok büyük değerler, sırasıyla hedef türün en düşük veya en büyük değerine ayarlanır.
Bu değişiklik, kayan noktalı sayıdan tamsayıya dönüşümlere yönelik .NET 9 değişikliğini sürdürür; bu değişiklik, float ve double türlerinden uint, long, ulong ve int türlerine yapılan dönüşümleri standartlaştırmıştır. .NET 11, doygunluk desteğini 8 ve 16 bitlik hedef türlere genişletir.
Değişiklik, buna yorumlayıcısı da dahil olan CoreCLR'ye ve Native AOT'ye uygulanır. Mono bu değişikliğe dahil değildir.
Daha fazla bilgi için bkz. dotnet/runtime#128604.
Sürüm kullanıma sunulmuştur
.NET 11 Önizleme 7
Önceki davranış
Daha önce .NET, değer hedef türün sınırlarını aştığında veya NaN olduğunda, denetlenmeyen kayan noktalı sayıdan tamsayıya dönüştürmenin sonucunu garanti etmiyordu. Sonuçlar, CoreCLR ve Mono gibi çalışma zamanı uygulamaları arasında, x86, x64, Arm32, Arm64 ve WebAssembly gibi mimariler arasında ve x87, SSE2, AVX ve AVX-512 gibi bir mimari içindeki donanım yönerge kümeleri arasında farklılık gösterebilir.
.NET 9'daki geriye dönük uyumluluğu bozan değişiklik, taşma durumunda dönüştürmelerin genellikle sentinel değerler döndürdüğü x86 ve x64 mimarilerini özellikle öne çıkardı. Arm64, yerleşik olarak zaten doygunluklu dönüşümler kullanıyordu. Bu değişiklik, eski sentinel sonuçlarını bir kural olarak belirlemek yerine, daha geniş tamsayı türlerine yapılan dönüşümleri standartlaştırdı.
Küçük integral türler için, .NET 9 ve .NET 10'da yaygın bir CoreCLR dönüştürme dizisi, int türüne doyumlu dönüştürme yapılması ve ardından yüksek bitlerin atılmasıyla hedef türe daraltma yapılması şeklindeydi. Bu dizi, birçok uygulamanın yaşadığı davranışı açıklar, ancak doğrudan kayan noktadan küçük tamserli atamaya yönelik garantili bir sözleşme değildir.
Aşağıdaki tabloda çalışma zamanı float veya double değeri için bu iki adımlı diziden elde edilen sonuçlar gösterilmektedir x. Bu girişler int içine sığar; bu nedenle örnekler, hedefin en düşük 8 ya da 16 biti dışındaki tüm bitlerin atılmasının etkisini yalıtır. Korunan bitler, sbyte ve ushort için işaretli, char, byte ve short için ise işaretsiz olarak yorumlanır. için char sonuçlar sayısal olarak gösterilir.
| Şuna dönüştür | Değeri x |
Korunan düşük bitler | Örnek önceki sonuç |
|---|---|---|---|
sbyte veya byte |
298 | 0x2A |
42 |
sbyte |
-298 | 0xD6 |
-42 |
byte |
-42 | 0xD6 |
214 |
short, ushort veya char |
65578 | 0x002A |
42 |
short |
-65578 | 0xFFD6 |
-42 |
ushort veya char |
-42 | 0xFFD6 |
65494 |
Örneğin, aşağıdaki kod döndürebilir 42:
static short ConvertValue(double value)
{
return unchecked((short)value);
}
short result = ConvertValue(65578.0);
Ara öğe int : 65578 (0x0001002A). Yalnızca düşük 16 biti korunursa, sonuç 42 (short.MaxValue) olur; 0x002A değerine doyurulmaz.
Yeni davranış
.NET 11'den itibaren, denetlenmeyen dönüşümler hedef türün sınır değerlerinde sabitlenir. Hedef aralık içindeki sonlu değerler sıfıra yuvarlanmaya devam eder.
NaN sıfıra dönüştürür.
| Şuna dönüştür | Negatif sonsuzluk da dahil olmak üzere en düşük değerin altında | Pozitif sonsuzluk da dahil olmak üzere maksimum değerin üzerinde | NaN |
|---|---|---|---|
sbyte |
-128 (sbyte.MinValue) |
127 (sbyte.MaxValue) |
0 |
byte |
0 (byte.MinValue) |
255 (byte.MaxValue) |
0 |
short |
-32768 (short.MinValue) |
32767 (short.MaxValue) |
0 |
ushort |
0 (ushort.MinValue) |
65535 (ushort.MaxValue) |
0 |
char |
0 (char.MinValue) |
65535 (char.MaxValue) |
0 |
Yukarıdaki örnek artık 32767 yerine 42 (short.MaxValue) döndürür. Benzer şekilde, 298 değerinden byte değerine yapılan bir dönüştürme artık 255 yerine 42 döndürür ve 65494 değerinden -42 değerine yapılan bir dönüştürme de artık 0 yerine ushort döndürür.
float üzerinden dönüştürüldükleri için, Half öğesinden yapılan karşılık gelen işaretlenmemiş dönüştürmeler de yeni davranışı kullanır.
ConvertToInteger<TInteger>(Single) ve ConvertToInteger<TInteger>(Double) artık bu küçük hedef veri türleri için doğru şekilde doygunluğa ulaşır.
Denetlenen dönüştürmeler değişmeden kalır ve dönüştürme sırasında taşma olduğunda OverflowException oluşturmaya devam eder. Bu değişiklik, tamsayıdan tamsayıya daraltma dönüştürmelerini veya .NET 9 değişikliğinin kapsadığı daha geniş tamsayı ve vektör dönüştürmelerini değiştirmez.
Kesinti yaratan değişiklik türü
Bu değişiklik davranışsal bir değişikliktir.
Değişiklik nedeni
.NET 9 değişikliği, daha geniş tamsayı türlerine yönelik dönüşümler için doyumlu davranışı yerleştirdi; ancak 8 bitlik ve 16 bitlik hedef türlere yapılan dönüşümlerde, aralık dışı değerler ve NaN için davranış hâlâ donanıma ve uygulamaya bağlıydı. Bu değişiklik, bu dönüştürmelere deterministik, satüre edici bir davranış kazandırır ve JIT, CoreCLR yorumlayıcısı ve Native AOT’teki önceden başlatılmış değerlerin birbiriyle uyumlu olmasını sağlar.
Önerilen eylem
Kodunuz aralık dışı girdiler için önceki sonuçlara dayanıyorsa, mümkün olduğunda hedef türün sınır değerlerinde doyuma ulaşılacağını varsayacak şekilde kodu güncelleyin.
Bu değişikliklerden önce yaygın olarak kullanılan platformun yerel davranışına ihtiyacınız varsa, en basit geçici çözüm ConvertToIntegerNative<TInteger>(Double) veya ConvertToIntegerNative<TInteger>(Single) kullanmaktır. Örneğin, double bir double.ConvertToIntegerNative<ushort>(x) olduğunda doğrudan float dönüştürmesini (ushort)x ile veya bir float.ConvertToIntegerNative<ushort>(x) olduğunda x ile değiştirin.
Ara dönüştürmeyi açıkça da seçebilirsiniz. Aşağıdaki örneklerde bir double giriş x ve bir ushort hedef kullanılmaktadır:
| Gerekli davranış | Conversion |
|---|---|
| Genellikle önceki davranışı geri kazandıran, hedef türe platforma özgü dönüştürme | double.ConvertToIntegerNative<ushort>(x) |
int değerine kadar doygunluk, ardından daraltma; yaygın .NET 9 ve .NET 10 CoreCLR dizisiyle eşleşen |
unchecked((ushort)(int)x) |
Önce int öğesine platforma özgü dönüştürme, ardından daraltma; .NET 9 öncesinde yaygın olan bir sıraya uyan |
unchecked((ushort)double.ConvertToIntegerNative<int>(x)) |
short girişleri için float kullanın ve byte, char, sbyte veya float.ConvertToIntegerNative yerine uygun hedef türünü kullanın.
.NET 9 değişikliğinde olduğu gibi, ConvertToIntegerNative, aralık dışı değerler veya NaN için önceki sonuçları yeniden üreteceği garanti edilmeyen bir öğedir. Geçerli platform için verimli olan ve çalışma zamanları, mimariler veya donanım düzeltmeleri arasında değişebilen davranışı seçer. Bunun yerine, (ushort)(int)x ifadesinin açıkça kullanılması, int'e doygunlaştırmalı bir dönüştürme ve ardından tamsayı daraltma seçer; geçmişteki tüm uygulamaların davranışını geri yüklemez.
Dönüştürülen değer dizi dizini, arabellek uzaklığı veya uzunluk olarak kullanılıyorsa, sonuçta elde edilen değerin gerekli sınırlar içinde olduğunu doğrulayın. Bir makinede kullanılabilir bir değer üreten dönüştürme, platforma özel dönüştürmenin başka bir makinede bunu yapacağını belirlemez.
Etkilenen API'ler
- Single veya Byte türünden Int16, UInt16, Double, SByte ya da Char türüne denetlenmeyen açık dönüştürmeler.
- Half işaretsiz açık dönüştürme işleçleri:
-
ConvertToInteger<TInteger>(Single), ByteInt16, UInt16, Char,
TIntegerveya SByte olduğunda. -
Byte, Int16, UInt16, Char,
TIntegerveya SByte olduğunda ConvertToInteger<TInteger>(Double).