Sdílet prostřednictvím


Numeric IntPtr

Poznámka

Tento článek je specifikace funkce. Specifikace slouží jako návrhový dokument pro funkci. Zahrnuje navrhované změny specifikace spolu s informacemi potřebnými při návrhu a vývoji funkce. Tyto články se publikují, dokud nebudou navrhované změny specifikace finalizovány a začleněny do aktuální specifikace ECMA.

Mezi specifikací funkce a dokončenou implementací může docházet k nějakým nesrovnalostem. Tyto rozdíly jsou zachyceny v poznámkách příslušné schůzky k návrhu jazyka (LDM) .

Další informace o procesu přijetí specifikací funkcí do jazyka C# najdete v článku o specifikacích .

Shrnutí

Toto je revize původní vlastnosti nativních celých čísel (specifikace), kde nint/nuint typy byly odlišné od základních typů System.IntPtr/System.UIntPtr. Stručně řečeno, nyní považujeme nint/nuint za jednoduché typy aliasing System.IntPtr/System.UIntPtr, stejně jako int ve vztahu k System.Int32. Příznak funkce modulu runtime System.Runtime.CompilerServices.RuntimeFeature.NumericIntPtr aktivuje toto nové chování.

Návrh

8.3.5 Jednoduché typy

Jazyk C# poskytuje sadu předdefinovaných typů struct označovaných jako jednoduché typy. Jednoduché typy jsou identifikovány prostřednictvím klíčových slov, ale tato klíčová slova jsou jednoduše aliasy pro předdefinované typy struct v oboru názvů System, jak je popsáno v následující tabulce.

klíčové slovo typ aliasu
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 Integrální typy

Jazyk C# podporuje jedenáct integrálních typů: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulonga char. [...]

8.8 Nespravované typy

Jinými slovy, unmanaged_type je jedna z následujících možností:

  • sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimalnebo bool.
  • Všechny enum_type.
  • Jakýkoli uživatelem definovaný struct_type, který není konstruovaný typ a obsahuje pouze pole unmanaged_types.
  • V nebezpečném kódu může být jakýkoli pointer_type.

10.2.3 Implicitní číselné převody

Implicitní číselné převody jsou:

  • Od sbyte po short, int, nint, long, float, doublenebo decimal.
  • Od byte po short, ushort, int, uint, nint, nuint, long, ulong, float, doublenebo decimal.
  • Od short po int, nint, long, float, doublenebo decimal.
  • Od ushort po int, uint, nint, nuint, long, ulong, float, doublenebo decimal.
  • Od int po nint, long, float, doublenebo decimal.
  • Od uint po nuint, long, ulong, float, doublenebo decimal.
  • od nint do long, float, doublenebo decimal.
  • od nuint do ulong, float, doublenebo decimal.
  • Od long po float, doublenebo decimal.
  • Od ulong po float, doublenebo decimal.
  • Od char po ushort, int, uint, nint, nuint, long, ulong, float, doublenebo decimal.
  • Od float do double.

[...]

10.2.11 Implicitní převody konstantních výrazů

Převod implicitního konstantního výrazu umožňuje následující převody:

  • constant_expression typu int lze převést na typ sbyte, byte, short, ushort, uint, nint, nuintnebo ulong, za předpokladu, že hodnota constant_expression je v rozsahu cílového typu. [...]

10.3.2 Explicitní číselné převody

Explicitní číselné převody jsou převody z numeric_type do jiného numeric_type, pro které implicitní číselný převod ještě neexistuje:

  • Od sbyte po byte, ushort, uint, nuint, ulongnebo char.
  • Od byte do sbyte nebo char.
  • Od short po sbyte, byte, ushort, uint, nuint, ulongnebo char.
  • Od ushort po sbyte, byte, shortnebo char.
  • Od int po sbyte, byte, short, ushort, uint, nuint, ulongnebo char.
  • Od uint po sbyte, byte, short, ushort, int, nintnebo char.
  • Od long po sbyte, byte, short, ushort, int, uint, nint, nuint, ulongnebo char.
  • nint sbyte, byte, short, ushort, int, uint, nuint, ulongnebo char.
  • nuint sbyte, byte, short, ushort, int, uint, nint, longnebo char.
  • Od ulong po sbyte, byte, short, ushort, int, uint, nint, nuint, longnebo char.
  • Od char po sbyte, bytenebo short.
  • Od float po sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, charnebo decimal.
  • Od double po sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, floatnebo decimal.
  • Od decimal po sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, floatnebo double.

[...]

10.3.3 Explicitní výčtové převody

Explicitní převody výčtu jsou:

  • Z sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, doublenebo decimal na jakýkoliv enum_type.
  • Z libovolné enum_type na sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, doublenebo decimal.
  • Z jakéhokoliv typu enum_type do jakéhokoliv jiného typu enum_type.

12.6.4.7 Lepší cíl převodu

Vzhledem ke dvěma typům T₁ a T₂je T₁lepším cílem převodu než T₂, pokud platí některá z následujících možností:

  • Implicitní převod z T₁ na T₂ existuje a neexistuje žádný implicitní převod z T₂ na T₁.
  • T₁ je Task<S₁>, T₂ je Task<S₂>a S₁ je lepším cílem převodu než S₂
  • T₁ je S₁ nebo S₁?, kde S₁ je celočíselný typ a T₂ je S₂ nebo S₂?, kde S₂ je celočíselný typ bez znaménka. Konkrétně: [...]

12.8.12 Přístup k elementům

[...] Počet výrazů v argument_list musí být stejný jako pořadí array_typea každý výraz musí být typu int, uint, nint, nuint, longnebo ulong, nebo implicitně převést na jeden nebo více těchto typů.

11.8.12.2 Přístup k poli

[...] Počet výrazů v argument_list musí být stejný jako pořadí array_typea každý výraz musí být typu int, uint, nint, nuint, longnebo ulong, nebo implicitně převést na jeden nebo více těchto typů.

[...] Zpracování přístupu k poli ve tvaru P[A], kde P je primární výraz pro vytvoření pole určitého typu pole a A je seznam argumentů, se skládá z následujících kroků: [...]

  • Výrazy indexu argument_list se vyhodnocují v pořadí zleva doprava. Po vyhodnocení každého výrazu indexu se provádí implicitní převod na jeden z následujících typů: int, uint, nint, nuint, long, ulong. První typ v tomto seznamu, pro který existuje implicitní převod, je vybrán. [...]

12.8.16 Operátory přírůstku a dekrementace

Rozlišení přetížení unárního operátoru se použije k výběru konkrétní implementace operátoru. Předdefinované operátory ++ a -- existují pro následující typy: sbyte, byte, short, ushort, int, uint, nint, nuint,long, ulong, char, float, double, decimala jakýkoli typ výčtu.

12.9.2 Unární operátor plus

Předdefinované unární operátory plus jsou:

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

12.9.3 Unární operátor minus

Předdefinované operátory unárního minusu jsou:

  • Celočíselná negace:

    ...
    nint operator –(nint x);
    

12.8.16 Operátory přírůstku a dekrementace

Předdefinované operátory ++ a -- existují pro následující typy: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimala libovolný typ výčtu.

11.7.19 Výrazy výchozí hodnoty

Kromě toho je default_value_expression konstantní výraz, pokud je typ jedním z následujících typů hodnot: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal, bool, nebo jakýkoli typ výčtu.

12.9.5 Bitový operátor doplňku

Předdefinované bitové doplňkové operátory jsou:

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

12.9.6 Operátory inkrementace a dekrementace předpon

Předdefinované operátory ++ a -- existují pro následující typy: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimala libovolný typ výčtu.

12.10 Aritmetické operátory

12.10.2 Operátor násobení

Předdefinované operátory násobení jsou uvedeny níže. Všechny operátory vypočítají součin x a y.

  • Celočíselné násobení:

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

12.10.3 Operátor dělení

Níže jsou uvedeny předdefinované operátory dělení. Všechny operátory vypočítají podíl x a y.

  • Celočíselné dělení:

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

12.10.4 Operátor zbytku

Níže jsou uvedeny předdefinované operátory zbytku. Operátoři vypočítají zbytek dělení z x na y.

  • Celý zbytek:

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

12.10.5 Operátor sčítání

  • Celočíselné sčítání:

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

12.10.6 Operátor odčítání

  • Odčítání celých čísel:

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

12.11 Posunové operátory

Níže jsou uvedeny předdefinované operátory posunu.

  • Posun doleva:

    ...
    nint operator <<(nint x, int count);
    nuint operator <<(nuint x, int count);
    
  • Posunout doprava:

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

    Operátor >> posune x doprava o počet bitů vypočítaný podle níže uvedených instrukcí.

    Pokud je x typu int, nint nebo long, zahodí se bity x s nízkým pořadím, zbývající bity se posunou doprava a pozice prázdných bitů s vysokým pořadím se nastaví na nulu, pokud je x nezáporná a nastaví se na jednu, pokud je x záporná.

    Pokud je x typu uint, nuint nebo ulong, bity x s nízkým pořadím se zahodí, zbývající bity se posunou doprava a pozice prázdných bitů s vysokým pořadím se nastaví na nulu.

  • Posun bez znaménka doprava:

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

Pro předdefinované operátory se počet bitů pro posun vypočítá takto: [...]

  • Pokud je typ xnint nebo nuint, počet posunů je dán nižšími pěti bity count na 32bitové platformě nebo nižšími šesti bity count na 64bitové platformě.

12.12 Relační operátory a operátory pro testování typů

12.12.2 Celočíselné relační operátory

Předdefinované celočíselné relační operátory jsou:

...
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 Logické operátory

12.12.2 Celočíselné logické operátory

Předdefinované celočíselné logické operátory jsou:

...
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 Konstantní výrazy

Konstantní výraz může být buď typ hodnoty, nebo odkazový typ. Pokud je konstantním výrazem typ hodnoty, musí to být jeden z následujících typů: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal, bool, nebo jakýkoli typ výčtu.

[...]

Implicitní převod konstantního výrazu umožňuje převést konstantní výraz typu int na sbyte, byte, short, ushort, uint, ulong nebo , za předpokladu, že hodnota konstantního výrazu je v rozsahu cílového typu.

Přístup k elementu Array 17.4

K prvkům pole se přistupuje pomocí výrazů element_access formuláře A[I₁, I₂, ..., Iₓ], kde A je výraz typu pole a každý Iₑ je výraz typu int, uint, nint, nuint,long, ulongnebo lze implicitně převést na jeden nebo více těchto typů. Výsledkem přístupu k prvku pole je proměnná, konkrétně prvek pole vybraný indexy.

23.5 Převody ukazatelů

23.5.1 Obecné

[...]

Kromě toho je v nezabezpečeném kontextu rozšířena sada dostupných explicitních převodů tak, aby zahrnovala následující explicitní převody ukazatelů:

  • Z jakéhokoli pointer_type do jakéhokoli jiného pointer_type.
  • Z sbyte, byte, short, ushort, int, uint, ,nint, nuint,,longnebo ulong na jakýkoli pointer_type.
  • Z libovolného pointer_type na sbyte, byte, short, ushort, int, uint, nint, nuint,longnebo ulong.

Přístup k prvku ukazatele 23.6.4

[...] Při přístupu prvku ukazatele P[E]formuláře musí být P výrazem jiného typu ukazatele než void*a E musí být výraz, který lze implicitně převést na int, uint, nint, nuint,longnebo ulong.

23.6.7 Aritmetika ukazatele

V nebezpečném kontextu lze operátor + a operátor použít na hodnoty všech typů ukazatelů s výjimkou void*. Proto pro každý typ ukazatele T*jsou implicitně definovány následující operátory:

[...]
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);

Výraz P typu ukazatele T* a výraz N typu int, uint, nint, nuint,longnebo ulong; výrazy P + N a N + P vypočítají hodnotu ukazatele typu T*, která vznikne přidáním N * sizeof(T) k adrese dané P. Podobně výraz P – N vypočítá hodnotu ukazatele typu T*, která má za následek odečtení N * sizeof(T) z adresy zadané P.

Různé aspekty

Zásadní změny

Jedním z hlavních dopadů tohoto návrhu je, že System.IntPtr a System.UIntPtr získají některé vestavěné operátory (převody, unární a binární).
Patří mezi ně checked operátory, což znamená, že následující operátory na těchto typech nyní vyvolají chybu při přetečení:

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

Kódování metadat

Tento návrh znamená, že nint a nuint lze jednoduše vygenerovat jako System.IntPtr a System.UIntPtrbez použití System.Runtime.CompilerServices.NativeIntegerAttribute.
Podobně lze při načítání metadat NativeIntegerAttribute ignorovat.