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.
Not
Bu makale bir özellik belirtimidir. Belirtim, özelliğin tasarım belgesi olarak görev alır. Önerilen belirtim değişikliklerini ve özelliğin tasarımı ve geliştirilmesi sırasında gereken bilgileri içerir. Bu makaleler, önerilen belirtim değişiklikleri son haline getirilene ve geçerli ECMA belirtimine dahil edilene kadar yayımlanır.
Özellik belirtimi ile tamamlanan uygulama arasında bazı tutarsızlıklar olabilir. Bu farklılıklar, ilgili dil tasarım toplantısı (LDM) notlarındakayıt altına alınmıştır.
Özellik belirtimlerini C# dil standardına benimseme işlemi hakkında daha fazla bilgi edinmek için
Şampiyon sorunu: https://github.com/dotnet/csharplang/issues/435
Özet
Yerel boyutlu imzalı ve imzasız tamsayı türleri için dil desteği.
Motivasyon birlikte çalışma senaryoları ve düşük düzeyli kitaplıklar içindir.
Tasarım
nint ve nuint tanımlayıcıları, yerel imzalı ve imzasız tamsayı türlerini temsil eden yeni bağlamsal anahtar sözcüklerdir.
Tanımlayıcılar yalnızca ad araması bu program konumunda uygun bir sonuç bulamadıklarında anahtar sözcük olarak değerlendirilir.
nint x = 3;
_ = nint.Equals(x, 3);
nint ve nuint türleri, derleyicinin bu türler için ek dönüştürmeler ve işlemler sağlayarak onları yerel tamsayılar olarak ön plana çıkardığı System.IntPtr ve System.UIntPtr temel türleri tarafından temsil edilir.
Sabit
Sabit ifadeler nint veya nuinttüründe olabilir.
Yerel int değişmez değerleri için doğrudan söz dizimi yoktur. Bunun yerine diğer tamsayı sabit değerlerinin örtük veya açık atamaları kullanılabilir: const nint i = (nint)42;.
nint sabitleri [ int.MinValue, int.MaxValue ] aralığındadır.
nuint sabitleri [ uint.MinValue, uint.MaxValue ] aralığındadır.
MinValue veya MaxValuenint veya nuint alanı yoktur çünkü nuint.MinValuedışında bu değerler sabit olarak yayılamaz.
Sabit katlama, tüm tekli işleçler { +, -, ~ } ve ikili işleçler { +, -, *, /, %, ==, !=, <, <=, >, >=, &, |, ^, <<, >> } için desteklenir.
Sabit katlama işlemleri, derleyici platformundan bağımsız olarak tutarlı davranış sağlamak amacıyla yerel int türleri yerine Int32 ve UInt32 işlenenleri kullanılarak değerlendirilir.
İşlem 32 bit sabit değerle sonuçlanırsa, derleme zamanında sabit katlama gerçekleştirilir.
Aksi takdirde işlem çalışma zamanında yürütülür ve sabit olarak kabul edilmez.
Dönüşüm
nint ile IntPtrarasında ve nuint ile UIntPtrarasında bir kimlik dönüştürmesi vardır.
Yerel tamsayılar ve yalnızca temel alınan türlere göre farklılık gösteren bileşik türler arasında bir kimlik dönüşümü vardır: diziler, Nullable<>, oluşturulan türler ve demetler.
Aşağıdaki tablolar özel türler arasındaki dönüştürmeleri kapsar.
(Her dönüştürme için IL, farklıysa unchecked ve checked bağlamları için varyantları içerir.)
Aşağıdaki tabloda genel notlar:
-
conv.u, yerel tamsayıya sıfır uzatmalı bir dönüşümdür veconv.i, yerel tamsayıya işaret uzatmalı bir dönüşümdür. - Hem
checkedhem de daraltma için bağlamları şunlardır:-
conv.ovf.*içinsigned to * -
conv.ovf.*.uniçinunsigned to *
-
-
uncheckediçin bağlamlar şunlardır:-
conv.i*içinsigned to *(burada * hedef genişliktir) -
conv.u*içinunsigned to *(burada * hedef genişliktir)
-
-
uncheckediçin bağlamlar şunlardır:-
conv.i*içinany to signed *(burada * hedef genişliktir) -
conv.u*içinany to unsigned *(burada * hedef genişliktir)
-
Birkaç örnek alınıyor:
-
sbyte to nintvesbyte to nuintconv.ikullanırken,byte to nintvebyte to nuintconv.ukullanıyor çünkü bunların hepsi genişletme. -
nint to bytevenuint to byteconv.u1kullanırkennint to sbytevenuint to sbyteconv.i1kullanır.byte,sbyte,shortveushortiçin "yığın türü"int32. Bu nedenleconv.i1etkin bir şekilde "imzalı bir bayta indirilir ve ardından int32'ye kadar imzalanır",conv.u1ise etkin bir şekilde "imzasız bir bayta indirilir ve sonra da sıfırdan int32'ye genişletilir". -
checked void* to nint,conv.ovf.i.un'i,checked void* to long'ninconv.ovf.i8.un'ü kullandığı şekilde kullanır.
| Işlenen | Hedef | Dönüşüm | Illinois |
|---|---|---|---|
object |
nint |
Kutudan çıkarma | unbox |
void* |
nint |
PointerToVoid | Nop/ conv.ovf.i.un |
sbyte |
nint |
Gizli Sayısal | conv.i |
byte |
nint |
Gizli Sayısal | conv.u |
short |
nint |
Gizli Sayısal | conv.i |
ushort |
nint |
Gizli Sayısal | conv.u |
int |
nint |
Gizli Sayısal | conv.i |
uint |
nint |
Açık Sayısal | conv.u / conv.ovf.i.un |
long |
nint |
Açık Sayısal | conv.i / conv.ovf.i |
ulong |
nint |
Açık Sayısal | conv.i / conv.ovf.i.un |
char |
nint |
Gizli Sayısal | conv.u |
float |
nint |
Açık Sayısal | conv.i / conv.ovf.i |
double |
nint |
Açık Sayısal | conv.i / conv.ovf.i |
decimal |
nint |
Açık Sayısal | long decimal.op_Explicit(decimal) conv.i / ... conv.ovf.i |
IntPtr |
nint |
Kimlik | |
UIntPtr |
nint |
Hiç kimse | |
object |
nuint |
Kutudan çıkarma | unbox |
void* |
nuint |
PointerToVoid | Nop |
sbyte |
nuint |
Açık Sayısal | conv.i / conv.ovf.u |
byte |
nuint |
Gizli Sayısal | conv.u |
short |
nuint |
Açık Sayısal | conv.i / conv.ovf.u |
ushort |
nuint |
Gizli Sayısal | conv.u |
int |
nuint |
Açık Sayısal | conv.i / conv.ovf.u |
uint |
nuint |
Gizli Sayısal | conv.u |
long |
nuint |
Açık Sayısal | conv.u / conv.ovf.u |
ulong |
nuint |
Açık Sayısal | conv.u / conv.ovf.u.un |
char |
nuint |
Gizli Sayısal | conv.u |
float |
nuint |
Açık Sayısal | conv.u / conv.ovf.u |
double |
nuint |
Açık Sayısal | conv.u / conv.ovf.u |
decimal |
nuint |
Açık Sayısal | ulong decimal.op_Explicit(decimal) conv.u / ... conv.ovf.u.un |
IntPtr |
nuint |
Hiç kimse | |
UIntPtr |
nuint |
Kimlik | |
| Sayım | nint |
Açık Belirtim | |
| Sayım | nuint |
Açık Belirtim |
| Işlenen | Hedef | Dönüşüm | Illinois |
|---|---|---|---|
nint |
object |
Boks | box |
nint |
void* |
PointerToVoid | Nop/ conv.ovf.u |
nint |
nuint |
Açık Sayısal |
conv.u (atlanabilir) / conv.ovf.u |
nint |
sbyte |
Açık Sayısal | conv.i1 / conv.ovf.i1 |
nint |
byte |
Açık Sayısal | conv.u1 / conv.ovf.u1 |
nint |
short |
Açık Sayısal | conv.i2 / conv.ovf.i2 |
nint |
ushort |
Açık Sayısal | conv.u2 / conv.ovf.u2 |
nint |
int |
Açık Sayısal | conv.i4 / conv.ovf.i4 |
nint |
uint |
Açık Sayısal | conv.u4 / conv.ovf.u4 |
nint |
long |
Gizli Sayısal | conv.i8 |
nint |
ulong |
Açık Sayısal | conv.i8 / conv.ovf.u8 |
nint |
char |
Açık Sayısal | conv.u2 / conv.ovf.u2 |
nint |
float |
Gizli Sayısal | conv.r4 |
nint |
double |
Gizli Sayısal | conv.r8 |
nint |
decimal |
Gizli Sayısal | conv.i8 decimal decimal.op_Implicit(long) |
nint |
IntPtr |
Kimlik | |
nint |
UIntPtr |
Hiç kimse | |
nint |
Sayım | Açık Belirtim | |
nuint |
object |
Boks | box |
nuint |
void* |
PointerToVoid | Nop |
nuint |
nint |
Açık Sayısal |
conv.i(atlanabilir) / conv.ovf.i.un |
nuint |
sbyte |
Açık Sayısal | conv.i1 / conv.ovf.i1.un |
nuint |
byte |
Açık Sayısal | conv.u1 / conv.ovf.u1.un |
nuint |
short |
Açık Sayısal | conv.i2 / conv.ovf.i2.un |
nuint |
ushort |
Açık Sayısal | conv.u2 / conv.ovf.u2.un |
nuint |
int |
Açık Sayısal | conv.i4 / conv.ovf.i4.un |
nuint |
uint |
Açık Sayısal | conv.u4 / conv.ovf.u4.un |
nuint |
long |
Açık Sayısal | conv.u8 / conv.ovf.i8.un |
nuint |
ulong |
Gizli Sayısal | conv.u8 |
nuint |
char |
Açık Sayısal | conv.u2 / conv.ovf.u2.un |
nuint |
float |
Gizli Sayısal | conv.r.un conv.r4 |
nuint |
double |
Gizli Sayısal | conv.r.un conv.r8 |
nuint |
decimal |
Gizli Sayısal | conv.u8 decimal decimal.op_Implicit(ulong) |
nuint |
IntPtr |
Hiç kimse | |
nuint |
UIntPtr |
Kimlik | |
nuint |
Sayım | Açık Belirtim |
A'den Nullable<B> dönüştürme:
-
A'danB'e bir kimlik dönüşümü veya örtük dönüşüm varsa, örtük null atanabilir dönüşüm; -
A'denB'e açık bir dönüştürme varsa, açık bir boş değer atanabilir dönüştürme yapılabilir; - aksi takdirde geçersiz.
Nullable<A>'den B dönüştürme:
- Kimlik veya örtük ya da açık sayısal dönüşüm varsa,
A'denB'e açık null dönüşümü yapın; - aksi takdirde geçersiz.
Nullable<A>'den Nullable<B> dönüştürme:
-
A'denB'e bir kimlik dönüşümü varsa; -
A'denB'ye örtük veya açık bir sayısal dönüşüm varsa, açık şekilde null atanabilir bir dönüştürme yapılabilir. - aksi takdirde geçersiz.
Işleç
Önceden tanımlanmış işleçler aşağıdaki gibidir.
İşlenenlerden en az biri
(Her işlecin IL'i, unchecked ve farklıysa checked bağlamları için varyantları içerir.)
| Tekli | İşleç İmzası | Illinois |
|---|---|---|
+ |
nint operator +(nint value) |
nop |
+ |
nuint operator +(nuint value) |
nop |
- |
nint operator -(nint value) |
neg |
~ |
nint operator ~(nint value) |
not |
~ |
nuint operator ~(nuint value) |
not |
| İkili | İşleç İmzası | Illinois |
|---|---|---|
+ |
nint operator +(nint left, nint right) |
add / add.ovf |
+ |
nuint operator +(nuint left, nuint right) |
add / add.ovf.un |
- |
nint operator -(nint left, nint right) |
sub / sub.ovf |
- |
nuint operator -(nuint left, nuint right) |
sub / sub.ovf.un |
* |
nint operator *(nint left, nint right) |
mul / mul.ovf |
* |
nuint operator *(nuint left, nuint right) |
mul / mul.ovf.un |
/ |
nint operator /(nint left, nint right) |
div |
/ |
nuint operator /(nuint left, nuint right) |
div.un |
% |
nint operator %(nint left, nint right) |
rem |
% |
nuint operator %(nuint left, nuint right) |
rem.un |
== |
bool operator ==(nint left, nint right) |
beq / ceq |
== |
bool operator ==(nuint left, nuint right) |
beq / ceq |
!= |
bool operator !=(nint left, nint right) |
bne |
!= |
bool operator !=(nuint left, nuint right) |
bne |
< |
bool operator <(nint left, nint right) |
blt / clt |
< |
bool operator <(nuint left, nuint right) |
blt.un / clt.un |
<= |
bool operator <=(nint left, nint right) |
ble |
<= |
bool operator <=(nuint left, nuint right) |
ble.un |
> |
bool operator >(nint left, nint right) |
bgt / cgt |
> |
bool operator >(nuint left, nuint right) |
bgt.un / cgt.un |
>= |
bool operator >=(nint left, nint right) |
bge |
>= |
bool operator >=(nuint left, nuint right) |
bge.un |
& |
nint operator &(nint left, nint right) |
and |
& |
nuint operator &(nuint left, nuint right) |
and |
| |
nint operator |(nint left, nint right) |
or |
| |
nuint operator |(nuint left, nuint right) |
or |
^ |
nint operator ^(nint left, nint right) |
xor |
^ |
nuint operator ^(nuint left, nuint right) |
xor |
<< |
nint operator <<(nint left, int right) |
shl |
<< |
nuint operator <<(nuint left, int right) |
shl |
>> |
nint operator >>(nint left, int right) |
shr |
>> |
nuint operator >>(nuint left, int right) |
shr.un |
Bazı ikili işleçler için IL işleçleri ek işlenen türlerini destekler (bkz. ECMA-335 III.1.5 İşlenen türü tablosu). Ancak C# tarafından desteklenen operand türleri kümesi, basitlik ve dildeki mevcut operatörlerle tutarlılık açısından sınırlıdır.
Bağımsız değişkenlerin ve dönüş türlerinin nint? ve nuint?olduğu işleçlerin yükseltilmiş sürümleri desteklenir.
Bileşik atama işlemleri, x op= y veya x yerel int'ler olduğu y önceden tanımlanmış işleçlere sahip diğer temel türlerle aynı kuralları izler.
Özellikle, ifade x = (T)(x op y)'in T türünde olduğu ve x'ün yalnızca bir kez değerlendirildiği durumlarda x olarak bağlanır.
Kaydırma işleçleri, sizeof(nint) 4 ise kaydırılacak bit sayısını 5 bit olarak, sizeof(nint) 8 ise 6 bit olarak maskelemelidir.
(C# belirtiminde §12.11) bölümüne bakın).
C#9 derleyicisi, önceki bir dil sürümüyle derlenirken önceden tanımlanmış yerel tamsayı işleçlerine bağlama hatalarını bildirir, ancak yerel tamsayılara ve yerel tamsayılardan önceden tanımlanmış dönüştürmelerin kullanılmasına izin verir.
csc -langversion:9 -t:library A.cs
public class A
{
public static nint F;
}
csc -langversion:8 -r:A.dll B.cs
class B : A
{
static void Main()
{
F = F + 1; // error: nint operator+ not available with -langversion:8
F = (System.IntPtr)F + 1; // ok
}
}
İşaretçi aritmetiği
Yerel tamsayı uzaklıklarına sahip işaretçi ekleme veya çıkarma işlemleri için C# dilinde önceden tanımlanmış işleç yoktur.
Bunun yerine, nint ve nuint değerleri long ve ulong olarak yükseltilir ve işaretçi aritmetiği bu türler için önceden tanımlanmış işleçler kullanır.
static T* AddLeftS(nint x, T* y) => x + y; // T* operator +(long left, T* right)
static T* AddLeftU(nuint x, T* y) => x + y; // T* operator +(ulong left, T* right)
static T* AddRightS(T* x, nint y) => x + y; // T* operator +(T* left, long right)
static T* AddRightU(T* x, nuint y) => x + y; // T* operator +(T* left, ulong right)
static T* SubRightS(T* x, nint y) => x - y; // T* operator -(T* left, long right)
static T* SubRightU(T* x, nuint y) => x - y; // T* operator -(T* left, ulong right)
İkili sayısal yükseltmeler
ikili sayısal yükseltmeleri bilgilendirici metin (bkz. C# belirtimindeki §12.4.7.3) aşağıdaki gibi güncelleştirilir:
- …
- Aksi takdirde, işlenenlerden biri
ulongtüründeyse, diğer işlenenulongtürüne dönüştürülür veya diğer işlenensbyte,short,int,nintveyalongtüründeyse bağlama zamanı hatası oluşur.- Aksi takdirde, işlenenlerden biri
nuinttüründeyse, diğer işlenennuinttürüne dönüştürülür veya diğer işlenensbyte,short,int,nintveyalongtüründeyse bağlama zamanı hatası oluşur.- Aksi halde, operantlardan biri
longtüründeyse, diğer operantlongtürüne dönüştürülür.- Aksi takdirde, işlenenlerden biri
uinttüründeyse ve diğer işlenensbyte,short,nint, veyainttüründeyse, her iki işlenen delongtürüne dönüştürülür.- Aksi halde, operantlardan biri
uinttüründeyse, diğer operantuinttürüne dönüştürülür.- Aksi takdirde, işlenenlerden biri
ninttüründeyse, diğer işlenenninttürüne dönüştürülür.- Aksi takdirde, her iki işlenen de
inttürüne dönüştürülür.
Dinamik
Dönüştürmeler ve işleçler derleyici tarafından sentezlenir ve temel IntPtr ve UIntPtr türlerinin bir parçası değildir.
Sonuç olarak bu dönüştürmeler ve işleçler için çalışma zamanı bağlayıcısından kullanılamaz dynamic.
nint x = 2;
nint y = x + x; // ok
dynamic d = x;
nint z = d + x; // RuntimeBinderException: '+' cannot be applied 'System.IntPtr' and 'System.IntPtr'
Tür üyeleri
nint veya nuint için tek oluşturucu parametresiz oluşturucudur.
Aşağıdaki System.IntPtr ve System.UIntPtrüyeleri,nint veya nuint'ten açıkça dışındadır:
// constructors
// arithmetic operators
// implicit and explicit conversions
public static readonly IntPtr Zero; // use 0 instead
public static int Size { get; } // use sizeof() instead
public static IntPtr Add(IntPtr pointer, int offset);
public static IntPtr Subtract(IntPtr pointer, int offset);
public int ToInt32();
public long ToInt64();
public void* ToPointer();
System.IntPtr ve System.UIntPtr'e örtük olarak eklenir. .NET Framework 4.7.2 için:
public override bool Equals(object obj);
public override int GetHashCode();
public override string ToString();
public string ToString(string format);
System.IntPtr ve System.UIntPtr örtülü olarak dahildir ve temel türlerin kullanımları karşılık gelen yerel tamsayı türleriyle değiştirilir.
Örneğin, IntPtrISerializable, IEquatable<IntPtr>, IComparable<IntPtr>uygularsa nintISerializable, IEquatable<nint>, IComparable<nint>uygular.
Geçersiz kılma, saklama ve uygulama
nint ve System.IntPtrile nuint ve System.UIntPtrgeçersiz kılma, gizleme ve uygulama için eşdeğer kabul edilir.
Aşırı yüklemeler yalnızca nint ve System.IntPtrile nuint ve System.UIntPtrfarklılık gösteremez.
Geçersiz kılmalar ve uygulamalar, yalnızca nint ve System.IntPtrveya nuint ve System.UIntPtrile sınırlı olarak farklılık gösterebilir.
Yöntemler, yalnızca nint ve System.IntPtrveya nuint ve System.UIntPtrile farklılık gösteren diğer yöntemleri gizler.
Çeşitli
dizi dizinleri olarak kullanılan nint ve nuint ifadeleri dönüştürme olmadan yayılır.
static object GetItem(object[] array, nint index)
{
return array[index]; // ok
}
nint ve nuint, C# dilinden enum temel türü olarak kullanılamaz.
enum E : nint // error: byte, sbyte, short, ushort, int, uint, long, or ulong expected
{
}
Okuma ve yazma işlemleri nint ve nuintiçin atomiktir.
Alanlar volatile ve ninttürleri için nuint olarak işaretlenebilir.
ECMA-334 15.5.4, temel tür enum veya System.IntPtr olan System.UIntPtr içermez.
default(nint) ve new nint()(nint)0eşdeğerdir; default(nuint) ve new nuint()(nuint)0eşdeğerdir.
typeof(nint), typeof(IntPtr)'dir; typeof(nuint), typeof(UIntPtr)'tür.
sizeof(nint) ve sizeof(nuint) desteklenir, ancak güvenli olmayan bir bağlamda derleme gerektirir (sizeof(IntPtr) ve sizeof(UIntPtr)için gerektiği gibi).
Değerler derleme zamanı sabitleri değildir.
sizeof(nint)
sizeof(IntPtr)yerine IntPtr.Size olarak uygulanır; sizeof(nuint)sizeof(UIntPtr)yerine UIntPtr.Size olarak uygulanır.
Tür başvurularını içeren derleyici tanılamaları, nint veya nuintyerine nint veya nuint'e ilişkin olarak IntPtr veya UIntPtr'ü raporlar.
Meta veriler
nint ve nuint meta verilerde System.IntPtr ve System.UIntPtrolarak gösterilir.
nint veya nuint içeren tür başvuruları, tür başvurusunun hangi bölümlerinin yerel int olduğunu belirtmek için bir System.Runtime.CompilerServices.NativeIntegerAttribute ile birlikte gönderilir.
namespace System.Runtime.CompilerServices
{
[AttributeUsage(
AttributeTargets.Class |
AttributeTargets.Event |
AttributeTargets.Field |
AttributeTargets.GenericParameter |
AttributeTargets.Parameter |
AttributeTargets.Property |
AttributeTargets.ReturnValue,
AllowMultiple = false,
Inherited = false)]
public sealed class NativeIntegerAttribute : Attribute
{
public NativeIntegerAttribute()
{
TransformFlags = new[] { true };
}
public NativeIntegerAttribute(bool[] flags)
{
TransformFlags = flags;
}
public readonly bool[] TransformFlags;
}
}
NativeIntegerAttribute ile tür başvurularının kodlaması NativeIntegerAttribute.mdkapsamındadır.
Alternatif
Yukarıdaki "tür silme" yaklaşımının bir alternatifi de yeni türleri tanıtmaktır: System.NativeInt ve System.NativeUInt.
public readonly struct NativeInt
{
public IntPtr Value;
}
Ayrı türler, IntPtr'dan farklı olarak aşırı yüklemeye izin verir ve ayrıca ayrıştırmayı ToString()'den farklı hale getirebilir.
Ancak CLR'nin bu türleri verimli bir şekilde işlemesi için daha fazla çalışma olacaktır ve bu da özelliğin birincil amacı olan verimliliği yener.
Ayrıca IntPtr kullanan mevcut yerel int koduyla birlikte çalışmak daha zor olacaktır.
Başka bir alternatif, çerçevedeki IntPtr için daha yerel int desteği eklemektir ancak belirli bir derleyici desteği olmadan.
Tüm yeni dönüştürmeler ve aritmetik işlemler derleyici tarafından otomatik olarak desteklenir.
Ancak dil anahtar sözcükler, sabitler veya checked işlemleri sağlamaz.
Tasarım toplantıları
- https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-05-26.md
- https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-06-13.md
- https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-07-05.md#native-int-and-intptr-operators
- https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-10-23.md
- https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-03-25.md
C# feature specifications