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
, ulong
a 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
,decimal
nebobool
. - 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
poshort
,int
,nint
,long
,float
,double
nebodecimal
. - Od
byte
poshort
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,float
,double
nebodecimal
. - Od
short
point
,nint
,long
,float
,double
nebodecimal
. - Od
ushort
point
,uint
,nint
,nuint
,long
,ulong
,float
,double
nebodecimal
. - Od
int
ponint
,long
,float
,double
nebodecimal
. - Od
uint
ponuint
,long
,ulong
,float
,double
nebodecimal
. -
od
nint
dolong
,float
,double
nebodecimal
. -
od
nuint
doulong
,float
,double
nebodecimal
. - Od
long
pofloat
,double
nebodecimal
. - Od
ulong
pofloat
,double
nebodecimal
. - Od
char
poushort
,int
,uint
,nint
,nuint
,long
,ulong
,float
,double
nebodecimal
. - Od
float
dodouble
.
[...]
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 typsbyte
,byte
,short
,ushort
,uint
,nint
,nuint
neboulong
, 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
pobyte
,ushort
,uint
,nuint
,ulong
nebochar
. - Od
byte
dosbyte
nebochar
. - Od
short
posbyte
,byte
,ushort
,uint
,nuint
,ulong
nebochar
. - Od
ushort
posbyte
,byte
,short
nebochar
. - Od
int
posbyte
,byte
,short
,ushort
,uint
,nuint
,ulong
nebochar
. - Od
uint
posbyte
,byte
,short
,ushort
,int
,nint
nebochar
. - Od
long
posbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,ulong
nebochar
. -
nint
sbyte
,byte
,short
,ushort
,int
,uint
,nuint
,ulong
nebochar
. -
nuint
sbyte
,byte
,short
,ushort
,int
,uint
,nint
,long
nebochar
. - Od
ulong
posbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
nebochar
. - Od
char
posbyte
,byte
neboshort
. - Od
float
posbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
nebodecimal
. - Od
double
posbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
,float
nebodecimal
. - Od
decimal
posbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
,float
nebodouble
.
[...]
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
,double
nebodecimal
na jakýkoliv enum_type. - Z libovolné enum_type na
sbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
,float
,double
nebodecimal
. - 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₁
naT₂
existuje a neexistuje žádný implicitní převod zT₂
naT₁
. -
T₁
jeTask<S₁>
,T₂
jeTask<S₂>
aS₁
je lepším cílem převodu nežS₂
-
T₁
jeS₁
neboS₁?
, kdeS₁
je celočíselný typ aT₂
jeS₂
neboS₂?
, kdeS₂
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
, long
nebo 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
, long
nebo 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
, decimal
a 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
, decimal
a 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
, decimal
a 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
>>
posunex
doprava o počet bitů vypočítaný podle níže uvedených instrukcí.Pokud je
x
typuint
,nint
nebolong
, zahodí se bityx
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 jex
nezáporná a nastaví se na jednu, pokud jex
záporná.Pokud je
x
typuuint
,nuint
neboulong
, bityx
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
x
nint
nebonuint
, počet posunů je dán nižšími pěti bitycount
na 32bitové platformě nebo nižšími šesti bitycount
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
, ulong
nebo 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
,,long
neboulong
na jakýkoli pointer_type. - Z libovolného pointer_type na
sbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
neboulong
.
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
,long
nebo 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
,long
nebo 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.UIntPtr
bez použití System.Runtime.CompilerServices.NativeIntegerAttribute
.
Podobně lze při načítání metadat NativeIntegerAttribute
ignorovat.
C# feature specifications