Delen via


Numeric IntPtr

Notitie

Dit artikel is een functiespecificatie. De specificatie fungeert als het ontwerpdocument voor de functie. Het bevat voorgestelde specificatiewijzigingen, samen met informatie die nodig is tijdens het ontwerp en de ontwikkeling van de functie. Deze artikelen worden gepubliceerd totdat de voorgestelde specificaties zijn voltooid en opgenomen in de huidige ECMA-specificatie.

Er kunnen enkele verschillen zijn tussen de functiespecificatie en de voltooide implementatie. Deze verschillen worden vastgelegd in de relevante LDM-notities (Language Design Meeting).

Meer informatie over het proces voor het aannemen van functiespeclets in de C#-taalstandaard vindt u in het artikel over de specificaties.

Samenvatting

Dit is een revisie van de oorspronkelijke native integers feature (specificatie), waarbij de nint/nuint typen verschilden van de onderliggende typen System.IntPtr/System.UIntPtr. Kortom, we behandelen nu nint/nuint als eenvoudige typen aliasing System.IntPtr/System.UIntPtr, zoals we doen voor int in relatie tot System.Int32. Met de System.Runtime.CompilerServices.RuntimeFeature.NumericIntPtr runtime-functievlag wordt dit nieuwe gedrag geactiveerd.

Ontwerpen

8.3.5 Eenvoudige typen

C# biedt een set vooraf gedefinieerde struct typen die de eenvoudige typen worden genoemd. De eenvoudige typen worden geïdentificeerd via trefwoorden, maar deze trefwoorden zijn gewoon aliassen voor vooraf gedefinieerde struct typen in de System naamruimte, zoals beschreven in de onderstaande tabel.

trefwoord gedefinieerd type
sbyte System.SByte
byte System.Byte
short System.Int16
ushort System.UInt16
int System.Int32
uint System.UInt32
nint System.IntPtr
nuint System.UIntPtr
long System.Int64
ulong System.UInt64
char System.Char
float System.Single
double System.Double
bool System.Boolean
decimal System.Decimal

[...]

8.3.6 Integrale typen

C# ondersteunt elf integrale typen: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulongen char. [...]

8.8 Niet-beheerde typen

Met andere woorden, een unmanaged_type is een van de volgende:

  • sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimalof bool.
  • Elke enum_type.
  • Door de gebruiker gedefinieerde struct_type die geen samengesteld type is en uitsluitend velden van unmanaged_typebevat.
  • In onveilige code, elke pointertype.

10.2.3 Impliciete numerieke conversies

De impliciete numerieke conversies zijn:

  • Van sbyte tot short, int, nint, long, float, doubleof decimal.
  • Van byte tot short, ushort, int, uint, nint, nuint, long, ulong, float, doubleof decimal.
  • Van short tot int, nint, long, float, double, of decimal.
  • Van ushort tot int, uint, nint, nuint, long, ulong, float, doubleof decimal.
  • Van int tot nint, long, float, doubleof decimal.
  • Van uint tot nuint, long, ulong, float, doubleof decimal.
  • van nint tot long, float, doubleof decimal.
  • van nuint tot ulong, float, doubleof decimal.
  • Van long tot float, double, of decimal.
  • Van ulong tot float, doubleof decimal.
  • Van char tot ushort, int, uint, nint, nuint, long, ulong, float, doubleof decimal.
  • Van float tot double.

[...]

10.2.11 Impliciete constante expressieconversies

Een impliciete conversie van constante expressies maakt de volgende conversies mogelijk:

  • Een constant_expression van het type int kan worden geconverteerd naar het type sbyte, byte, short, ushort, uint, nint, nuintof ulong, mits de waarde van de constant_expression binnen het bereik van het doeltype valt. [...]

10.3.2 Expliciete numerieke conversies

De expliciete numerieke conversies zijn de conversies van een numeric_type naar een andere numeric_type waarvoor nog geen impliciete numerieke conversie bestaat:

  • Van sbyte tot byte, ushort, uint, nuint, ulongof char.
  • Van byte tot sbyte of char.
  • Van short tot sbyte, byte, ushort, uint, nuint, ulongof char.
  • Van ushort tot sbyte, byte, shortof char.
  • Van int naar sbyte, byte, short, ushort, uint, nuint, ulongof char.
  • Van uint tot sbyte, byte, short, ushort, int, nintof char.
  • Van long tot sbyte, byte, short, ushort, int, uint, ,nint, nuint,, ulongof char.
  • van nint tot sbyte, byte, short, ushort, int, uint, nuint, ulongof char.
  • van nuint tot sbyte, byte, short, ushort, int, uint, nint, longof char.
  • Van ulong tot sbyte, byte, short, ushort, int, uint, ,nint, nuint,, longof char.
  • Van char tot sbyte, byteof short.
  • Van float tot sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, charof decimal.
  • Van double tot sbyte, byte, short, ushort, int, uint, ,nint, nuint,, long, ulong, char, floatof decimal.
  • Van decimal tot sbyte, byte, short, ushort, int, uint, ,nint, nuint, long, ulong, char, floatof double.

[...]

10.3.3 Expliciete opsommingsomzettingen

De expliciete opsommingsconversies zijn:

  • Van sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, of decimal op een enum_type.
  • Van enum_type tot sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, doubleof decimal.
  • Van elke enum_type naar elke andere enum_type.

12.6.4.7 Beter conversiedoel

Als we de twee typen T₁ en T₂beschouwen, is T₁ een betere conversiedoel dan T₂ als een van de volgende voorwaarden geldt:

  • Er bestaat een impliciete conversie van T₁ naar T₂ en er bestaat geen impliciete conversie van T₂ naar T₁
  • T₁ is Task<S₁>, T₂ is Task<S₂>en S₁ is een beter conversiedoel dan S₂
  • T₁ is S₁ of S₁? waarbij S₁ een ondertekend integraal type is en T₂ is S₂ of S₂? waarbij S₂ een niet-ondertekend integraaltype is. Specifiek: [...]

12.8.12 Elementtoegang

[...] Het aantal expressies in de argument_list moet gelijk zijn aan de rang van de array_typeen elke expressie moet van het type int, uint, nint, nuint, longof ulong, zijn of impliciet kunnen worden omgezet in een of meer van deze typen.

11.8.12.2 Matrixtoegang

[...] Het aantal expressies in de argument_list moet gelijk zijn aan de rang van de array_typeen elke expressie moet van het type int, uint, nint, nuint, longof ulong, zijn of impliciet kunnen worden omgezet in een of meer van deze typen.

[...] De tijdsverwerking van een arraytoegang van het formulier P[A], waarbij P een primary_no_array_creation_expression is van een arraytype en A een argument_listis, bestaat uit de volgende stappen: [...]

  • De indexexpressies van de argument_list worden op volgorde geëvalueerd, van links naar rechts. Na de evaluatie van elke indexexpressie wordt een impliciete conversie naar een van de volgende typen uitgevoerd: int, uint, nint, nuint, long, ulong. Het eerste type in deze lijst waarvoor een impliciete conversie bestaat, wordt gekozen. [...]

12.8.16 Postfix incrementeer- en decrementeeroperatoren

De overbelastingsresolutie van unaire operatoren wordt gebruikt om een specifieke operatorimplementatie te selecteren. Vooraf gedefinieerde operatoren voor ++ en -- bestaan voor de volgende typen: sbyte, byte, short, ushort, int, uint, nint, nuint,long, ulong, char, float, double, decimalen elk enumtype.

12.9.2 Unary plus operator

De vooraf gedefinieerde unaire plusoperators zijn:

...
nint operator +(nint x);
nuint operator +(nuint x);

12.9.3 Unaire mintekenoperator

De vooraf gedefinieerd unaire minus-operatoren zijn:

  • Negatie van gehele getallen:

    ...
    nint operator –(nint x);
    

12.8.16 Postfix-increment- en decrementoperatoren

Vooraf gedefinieerde ++- en -- operators bestaan voor de volgende typen: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimalen een opsommingstype.

11.7.19 Standaardwaardeexpressies

Bovendien is een default_value_expression een constante expressie als het type een van de volgende waardetypen is: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal, bool, of een opsommingstype.

12.9.5 Bitsgewijze complementoperator

De vooraf gedefinieerde bitsgewijze complementoperators zijn:

...
nint operator ~(nint x);
nuint operator ~(nuint x);

12.9.6 Prefix-verhogings- en verlagingsoperatoren

Vooraf gedefinieerde ++- en -- operators bestaan voor de volgende typen: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimalen een opsommingstype.

12.10 Rekenkundige operatoren

12.10.2 Vermenigvuldigingsoperator

De vooraf gedefinieerde vermenigvuldigingsoperatoren worden hieronder vermeld. De operators berekenen allemaal het product van x en y.

  • Vermenigvuldiging van gehele getallen:

    ...
    nint operator *(nint x, nint y);
    nuint operator *(nuint x, nuint y);
    

12.10.3 Divisieoperator

Hieronder vindt u de vooraf gedefinieerde divisieoperators. De operators berekenen allemaal het quotiënt van x en y.

  • Deling van gehele getallen:

    ...
    nint operator /(nint x, nint y);
    nuint operator /(nuint x, nuint y);
    

Operator 12.10.4 Rest

De vooraf gedefinieerde restoperators worden hieronder weergegeven. De operators berekenen allemaal de rest van de deling tussen x en y.

  • Restgetal geheel getal:

    ...
    nint operator %(nint x, nint y);
    nuint operator %(nuint x, nuint y);
    

12.10.5 Optellen operator

  • Optellen van gehele getallen:

    ...
    nint operator +(nint x, nint y);
    nuint operator +(nuint x, nuint y);
    

12.10.6 Aftrekkingsoperator

  • Geheel getal aftrekken:

    ...
    nint operator –(nint x, nint y);
    nuint operator –(nuint x, nuint y);
    

12.11 Shift-operatoren

De vooraf gedefinieerde shiftoperators worden hieronder weergegeven.

  • Naar links verschuiven:

    ...
    nint operator <<(nint x, int count);
    nuint operator <<(nuint x, int count);
    
  • Naar rechts gaan:

    ...
    nint operator >>(nint x, int count);
    nuint operator >>(nuint x, int count);
    

    De operator >> verschuift x naar rechts door een aantal bits dat is berekend, zoals hieronder wordt beschreven.

    Wanneer x van het type int, nint of longis, worden de laagwaardige bits van x verwijderd, worden de resterende bits naar rechts verschoven, en worden de hoogwaardige lege bitposities ingesteld op nul als x niet-negatief is en op één als x negatief is.

    Wanneer x van het type uint, nuint of ulongis, worden de lage volgorde van x verwijderd, worden de resterende bits naar rechts verplaatst en worden de lege bitposities in hoge volgorde ingesteld op nul.

  • Niet-ondertekende dienst rechts:

    ...
    nint operator >>>(nint x, int count);
    nuint operator >>>(nuint x, int count);
    

Voor de vooraf gedefinieerde operators wordt het aantal bits dat moet worden verplaatst als volgt berekend: [...]

  • Wanneer het type xnint of nuintis, wordt het aantal verschuivingen gegeven door de laagste vijf bits van count op een 32-bits platform of de zes laagste bits van count op een 64-bits platform.

12.12 Relationele en typetestoperators

12.12.2 Vergelijkingsoperatoren voor gehele getallen

De vooraf gedefinieerde vergelijkingsoperatoren voor gehele getallen zijn:

...
bool operator ==(nint x, nint y);
bool operator ==(nuint x, nuint y);

bool operator !=(nint x, nint y);
bool operator !=(nuint x, nuint y);

bool operator <(nint x, nint y);
bool operator <(nuint x, nuint y);

bool operator >(nint x, nint y);
bool operator >(nuint x, nuint y);

bool operator <=(nint x, nint y);
bool operator <=(nuint x, nuint y);

bool operator >=(nint x, nint y);
bool operator >=(nuint x, nuint y);

12.12 Logische operators

12.12.2 Logische operatoren voor gehele getallen

De vooraf gedefinieerde logische operatoren voor gehele getallen zijn:

...
nint operator &(nint x, nint y);
nuint operator &(nuint x, nuint y);

nint operator |(nint x, nint y);
nuint operator |(nuint x, nuint y);

nint operator ^(nint x, nint y);
nuint operator ^(nuint x, nuint y);

12.22 Constante uitdrukkingen

Een constante expressie kan een waardetype of een verwijzingstype zijn. Als een constante expressie een waardetype is, moet dit een van de volgende typen zijn: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal, bool, of een opsommingstype.

[...]

Bij een impliciete expressieconversie kan een constante expressie van het type int worden geconverteerd naar sbyte, byte, short, ushort, uint, nint, nuint, of ulong, mits de waarde van de constante expressie binnen het bereik van het doeltype valt.

17.4 Toegang tot matrixelementen

Matrixelementen worden geopend met behulp van element_access expressies van het formulier A[I₁, I₂, ..., Iₓ], waarbij A een expressie van een matrixtype is en elke Iₑ een expressie is van het type int, uint, nint, nuint,long, ulongof impliciet kan worden geconverteerd naar een of meer van deze typen. Het resultaat van toegang tot een matrixelement is een variabele, namelijk het matrixelement dat door de indexen is geselecteerd.

23.5 Aanwijzerconversies

23.5.1 Algemeen

[...]

Bovendien wordt in een onveilige context de set beschikbare expliciete conversies uitgebreid met de volgende expliciete aanwijzerconversies:

  • Van elke pointer_type naar elke andere pointer_type.
  • Van sbyte, byte, short, ushort, int, uint, nint, nuint,longof ulong op een pointer_type.
  • Van pointer_type tot sbyte, byte, short, ushort, int, uint, nint, nuint,long, tot ulong.

23.6.4 Toegang tot aanwijzerelementen

[...] In een verwijzingselementtoegang van het formulier P[E]moet P een expressie zijn van een ander type aanwijzer dan void*en moet E een expressie zijn die impliciet kan worden geconverteerd naar int, uint, nint, nuint,longof ulong.

23.6.7 Pointer-aritmetica

In een onveilige context kunnen de operator + en worden toegepast op waarden van alle typen aanwijzers, met uitzondering van void*. Voor elk type aanwijzer T*worden de volgende operators dus impliciet gedefinieerd:

[...]
T* operator +(T* x, nint y);
T* operator +(T* x, nuint y);
T* operator +(nint x, T* y);
T* operator +(nuint x, T* y);
T* operator -(T* x, nint y);
T* operator -(T* x, nuint y);

Gezien een expressie P van een aanwijzertype T* en een expressie N van het type int, uint, nint, nuint,longof ulong, berekenen de expressies P + N en N + P de aanwijzerwaarde van het type T* die voortkomt uit het optellen van N * sizeof(T) bij het adres opgegeven door P. Op dezelfde manier berekent de expressie P – N de aanwijzerwaarde van het type T* die het gevolg is van het aftrekken van N * sizeof(T) van het adres dat is opgegeven door P.

Verschillende overwegingen

Belangrijke wijzigingen

Een van de belangrijkste gevolgen van dit ontwerp is dat System.IntPtr en System.UIntPtr enkele ingebouwde operators (conversies, unaire en binaire) krijgen.
Deze omvatten checked operators, wat betekent dat de volgende operators op deze typen nu worden gegenereerd wanneer deze overlopen:

  • IntPtr + int
  • IntPtr - int
  • IntPtr -> int
  • long -> IntPtr
  • void* -> IntPtr

Metagegevenscodering

Dit ontwerp betekent dat nint en nuint eenvoudig kunnen worden verzonden als System.IntPtr en System.UIntPtr, zonder gebruik te maken van System.Runtime.CompilerServices.NativeIntegerAttribute.
Op dezelfde manier kan NativeIntegerAttribute worden genegeerd bij het laden van metagegevens.