Liczbowy IntPtr
Notatka
Ten artykuł jest specyfikacją funkcji. Specyfikacja służy jako dokument projektowy dla funkcji. Zawiera proponowane zmiany specyfikacji wraz z informacjami wymaganymi podczas projektowania i opracowywania funkcji. Te artykuły są publikowane do momentu sfinalizowania proponowanych zmian specyfikacji i włączenia ich do obecnej specyfikacji ECMA.
Mogą wystąpić pewne rozbieżności między specyfikacją funkcji a ukończoną implementacją. Te różnice są przechwytywane w odpowiednich spotkania projektowego języka (LDM).
Więcej informacji na temat procesu wdrażania specyfikacji funkcji można znaleźć w standardzie języka C# w artykule dotyczącym specyfikacji .
Streszczenie
Jest to poprawka początkowej funkcji natywnych liczb całkowitych (specyfikacja), gdzie typy nint
/nuint
były różne od bazowych typów System.IntPtr
/System.UIntPtr
.
Krótko mówiąc, traktujemy nint
/nuint
jako proste typy aliasujące System.IntPtr
/System.UIntPtr
, tak jak w przypadku int
w odniesieniu do System.Int32
. Flaga funkcji środowiska uruchomieniowego System.Runtime.CompilerServices.RuntimeFeature.NumericIntPtr
wyzwala to nowe zachowanie.
Projekt
8.3.5 Typy proste
Język C# udostępnia zestaw wstępnie zdefiniowanych typów struct
nazywanych prostymi typami. Proste typy są identyfikowane za pomocą słów kluczowych, ale te słowa kluczowe są po prostu aliasami dla wstępnie zdefiniowanych typów struct
w przestrzeni nazw System
, jak opisano w poniższej tabeli.
słowo kluczowe | typ z aliasem |
---|---|
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 |
[...]
Typy całkowite 8.3.6
C# obsługuje jedenaście typów całkowitych: sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
i char
. [...]
8.8 Typy niezarządzane
Innymi słowy, unmanaged_type jest jednym z następujących:
-
sbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
,float
,double
,decimal
lubbool
. - Dowolny enum_type.
- Każdy zdefiniowany przez użytkownika struct_type, który nie jest typem skonstruowanym i zawiera tylko pola typu unmanaged_type.
- W niebezpiecznym kodzie dowolny typ_wskaźnika.
10.2.3 Niejawne konwersje liczbowe
Niejawne konwersje liczbowe to:
- Od
sbyte
doshort
,int
,nint
,long
,float
,double
lubdecimal
. - Z
byte
doshort
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,float
double
lubdecimal
. - Od
short
doint
,nint
,long
,float
,double
lubdecimal
. - Z
ushort
doint
,uint
,nint
,nuint
,long
,ulong
,float
,double
lubdecimal
. - Od
int
donint
,long
,float
,double
lubdecimal
. - Od
uint
donuint
,long
,ulong
,float
,double
lubdecimal
. -
Od
nint
dolong
,float
,double
lubdecimal
. -
Od
nuint
doulong
,float
,double
lubdecimal
. - Z
long
dofloat
,double
lubdecimal
. - Z
ulong
dofloat
,double
lubdecimal
. - Od
char
doushort
,int
,uint
,nint
,nuint
,long
,ulong
,float
,double
lubdecimal
. - Z
float
dodouble
.
[...]
10.2.11 Niejawne konwersje wyrażeń stałych
Niejawna konwersja wyrażenia stałego zezwala na następujące konwersje:
-
constant_expression typu
int
można przekonwertować na typsbyte
,byte
,short
,ushort
,uint
,nint
,nuint
lubulong
, pod warunkiem, że wartość constant_expression mieści się w zakresie typu docelowego. [...]
10.3.2 Jawne konwersje liczbowe
Jawne konwersje liczbowe to konwersje z numeric_type do innej numeric_type, dla której nie istnieje jeszcze niejawna konwersja liczbowa:
- Od
sbyte
dobyte
,ushort
,uint
,nuint
,ulong
lubchar
. - Z
byte
dosbyte
lubchar
. - Od
short
dosbyte
,byte
,ushort
,uint
,nuint
,ulong
lubchar
. - Z
ushort
dosbyte
,byte
,short
lubchar
. - Z
int
dosbyte
,byte
,short
,ushort
,uint
,nuint
,ulong
lubchar
. - Od
uint
dosbyte
,byte
,short
,ushort
,int
,nint
lubchar
. - Od
long
dosbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,ulong
lubchar
. -
Od
nint
dosbyte
,byte
,short
,ushort
,int
,uint
,nuint
,ulong
lubchar
. -
Od
nuint
dosbyte
,byte
,short
,ushort
,int
,uint
,nint
,long
lubchar
. - Od
ulong
dosbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
lubchar
. - Z
char
dosbyte
,byte
lubshort
. - Z
float
dosbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
lubdecimal
. - Od
double
dosbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
,float
lubdecimal
. - Od
decimal
dosbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
,float
lubdouble
.
[...]
10.3.3 Jawne konwersje typu wyliczeniowego
Jawne konwersje wyliczenia to:
- Z
sbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
,float
,double
lubdecimal
do dowolnego enum_type. - Od dowolnego enum_type do
sbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
,ulong
,char
,float
,double
lubdecimal
. - Z dowolnego enum_type do dowolnego innego enum_type.
12.6.4.7 Lepszy cel konwersji
Biorąc pod uwagę dwa typy T₁
i T₂
, T₁
jest lepszym celem konwersji niż T₂
, jeśli spełniony jest jeden z następujących warunków:
- Istnieje niejawna konwersja z
T₁
naT₂
i nie istnieje niejawna konwersja zT₂
naT₁
-
T₁
jestTask<S₁>
,T₂
jestTask<S₂>
, aS₁
jest lepszym celem konwersji niżS₂
-
T₁
jestS₁
lubS₁?
, gdzieS₁
jest typem całkowitoliczbowym ze znakiem, aT₂
jestS₂
lubS₂?
, gdzieS₂
jest typem całkowitoliczbowym bez znaku. W szczególności: [...]
12.8.12 Dostęp do elementów
[...] Liczba wyrażeń w argument_list jest taka sama jak ranga array_type, a każde wyrażenie jest typu int
, uint
, nint
, nuint
, long
lub ulong,
lub niejawnie konwertowane na co najmniej jeden z tych typów.
11.8.12.2 Dostęp do tablicy
[...] Liczba wyrażeń w argument_list jest taka sama jak ranga array_type, a każde wyrażenie jest typu int
, uint
, nint
, nuint
, long
lub ulong,
lub niejawnie konwertowane na co najmniej jeden z tych typów.
[...] Przetwarzanie w czasie wykonywania dostępu do tablicy formularza P[A]
, gdzie P
jest primary_no_array_creation_expressionarray_type i A
jest argument_list, składa się z następujących kroków: [...]
- Wyrażenia indeksu argument_list są oceniane w kolejności od lewej do prawej. Po przeprowadzeniu oceny każdego wyrażenia indeksu wykonywana jest niejawna konwersja na jeden z następujących typów:
int
,uint
,nint
,nuint
,long
,ulong
. Pierwszy typ na tej liście, dla którego istnieje niejawna konwersja, zostaje wybrany. [...]
12.8.16 Operatory przyrostku i dekrementacji
Rozpoznawanie przeciążenia operatora jednoargumentowego jest stosowane w celu wybrania określonej implementacji operatora. Wstępnie zdefiniowane operatory ++
i --
istnieją dla następujących typów: sbyte
, byte
, short
, ushort
, int
, uint
, ,nint
, nuint
,,long
, ulong
, char
, float
, double
, decimal
i dowolny typ wyliczenia.
12.9.2 Operator jednoargumentowego plusa
Wstępnie zdefiniowane jednoargumentowe operatory plus to:
...
nint operator +(nint x);
nuint operator +(nuint x);
12.9.3 Jednoargumentowy operator minus
Wstępnie zdefiniowane unarne operatory minus to:
Negacja liczb całkowitych:
... nint operator –(nint x);
12.8.16 Operatory przyrostku i dekrementacji
Wstępnie zdefiniowane operatory ++
i --
istnieją dla następujących typów: sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
, char
, float
, double
, decimal
i dowolny typ wyliczenia.
11.7.19 Wyrażenia wartości domyślnej
Ponadto default_value_expression jest wyrażeniem stałym, jeśli typ jest jednym z następujących typów wartości: sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
, char
, float
, double
, decimal
, bool,
lub dowolny typ wyliczenia.
Operator uzupełniania bitowego 12.9.5
Wstępnie zdefiniowane operatory uzupełniania bitowego to:
...
nint operator ~(nint x);
nuint operator ~(nuint x);
12.9.6 Operatory preinkrementacji i predekrementacji
Wstępnie zdefiniowane operatory ++
i --
istnieją dla następujących typów: sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
, char
, float
, double
, decimal
i dowolny typ wyliczenia.
12.10 Operatory arytmetyczne
Operator mnożenia 12.10.2
Poniżej wymieniono wstępnie zdefiniowane operatory mnożenia. Wszyscy operatorzy obliczają produkt x
i y
.
Mnożenie liczb całkowitych:
... nint operator *(nint x, nint y); nuint operator *(nuint x, nuint y);
Operator dzielenia 12.10.3
Poniżej wymieniono wstępnie zdefiniowane operatory dzielenia. Wszystkie operatory obliczają iloraz x
i y
.
Dzielenie liczb całkowitych:
... nint operator /(nint x, nint y); nuint operator /(nuint x, nuint y);
12.10.4 Operator reszty
Poniżej wymieniono wstępnie zdefiniowane operatory pozostałe. Operatory obliczają pozostałą część podziału między x
a y
.
Pozostała liczba całkowita:
... nint operator %(nint x, nint y); nuint operator %(nuint x, nuint y);
12.10.5 Operator dodawania
Dodawanie liczb całkowitych
... nint operator +(nint x, nint y); nuint operator +(nuint x, nuint y);
12.10.6 Operator odejmowania
Odejmowanie liczb
... nint operator –(nint x, nint y); nuint operator –(nuint x, nuint y);
12.11 Operatory przesunięcia
Poniżej wymieniono predefiniowane operatory przesunięcia.
Shift w lewo:
... nint operator <<(nint x, int count); nuint operator <<(nuint x, int count);
Przesuń w prawo:
... nint operator >>(nint x, int count); nuint operator >>(nuint x, int count);
Operator
>>
zmieniax
w prawo przez kilka bitów obliczonych zgodnie z poniższym opisem.Gdy
x
jest typuint
,nint
lublong
, bity o niskiej kolejnościx
są odrzucane, pozostałe bity są przesunięte w prawo, a puste pozycje bitów o wysokiej kolejności są ustawione na zero, jeślix
jest nie ujemna i ustawiona na jedną, jeślix
jest ujemna.Gdy
x
jest typuuint
,nuint
lubulong
, bity o niskiej kolejnościx
są odrzucane, pozostałe bity są przesunięte w prawo, a puste pozycje bitów o wysokiej kolejności są ustawione na zero.Niepodpisane przesunięcie w prawo:
... nint operator >>>(nint x, int count); nuint operator >>>(nuint x, int count);
W przypadku wstępnie zdefiniowanych operatorów liczba bitów do przesunięcia jest obliczana w następujący sposób: [...]
- Gdy typ
x
jestnint
lubnuint
, liczba zmian jest podawana przez pięć bitów o niskiej kolejnościcount
na platformie 32-bitowej lub sześć bitów niższej kolejnościcount
na platformie 64-bitowej.
12.12 Operatory relacyjne i testujące typy
12.12.2 Operatory porównania liczb całkowitych
Wstępnie zdefiniowane operatory porównania liczb całkowitych to:
...
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 Operatory logiczne
Operatory logiczne dla liczb całkowitych
Wstępnie zdefiniowane operatory logiczne liczby całkowitej to:
...
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 Wyrażenia stałe
Wyrażenie stałe może być typem wartości lub typem odwołania. Jeśli wyrażenie stałe jest typem wartości, musi być jednym z następujących typów: sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
, char
, float
, double
, decimal
, bool,
lub dowolny typ wyliczenia.
[...]
Niejawna konwersja wyrażenia stałego umożliwia konwersję wyrażenia stałego typu int
na sbyte
, byte
, short
, ushort
, uint
, nint
, nuint
, lub ulong
, pod warunkiem, że wartość wyrażenia stałego mieści się w zakresie typu docelowego.
17.4 Dostęp do elementu tablicy
Dostęp do elementów tablicy uzyskuje się przy użyciu wyrażeń element_access formularza A[I₁, I₂, ..., Iₓ]
, gdzie A
jest wyrażeniem typu tablicy, a każdy Iₑ
jest wyrażeniem typu int
, uint
, nint
, nuint
,long
, ulong
lub może zostać niejawnie przekonwertowany na co najmniej jeden z tych typów. Wynikiem dostępu do elementu tablicy jest zmienna, czyli element tablicy wybrany przez indeksy.
23.5 Konwersje wskaźników
23.5.1 Ogólne
[...]
Ponadto w niebezpiecznym kontekście zestaw dostępnych jawnych konwersji rozszerza się, aby uwzględniać następujące jawne konwersje wskaźników:
- Z dowolnego pointer_type do dowolnego pointer_type.
- Z
sbyte
,byte
,short
,ushort
,int
,uint
, ,nint
,nuint
,,long
lubulong
do dowolnego pointer_type. - Z dowolnego pointer_type do
sbyte
,byte
,short
,ushort
,int
,uint
,nint
,nuint
,long
lubulong
.
23.6.4 Dostęp do elementu wskaźnika
[...] W przypadku dostępu do elementu wskaźnika w formie P[E]
, P
musi być wyrażeniem typu wskaźnika innego niż void*
, a E
musi być wyrażeniem, które można niejawnie przekonwertować na int
, uint
, nint
, nuint
,long
lub ulong
.
23.6.7 Arytmetyka wskaźnika
W niebezpiecznym kontekście operator +
i operator –
można zastosować do wartości wszystkich typów wskaźników z wyjątkiem void*
. W związku z tym dla każdego typu wskaźnika T*
następujące operatory są niejawnie zdefiniowane:
[...]
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);
Biorąc pod uwagę wyrażenie P
typu wskaźnika T*
i wyrażenie N
typu int
, uint
, nint
, nuint
,long
lub ulong
, wyrażenia P + N
i N + P
obliczają wartość wskaźnika typu T*
, która wynika z dodawania N * sizeof(T)
do adresu podanego przez P
. Podobnie wyrażenie P – N
oblicza wartość wskaźnika typu T*
wynikającą z odejmowania N * sizeof(T)
z adresu podanego przez P
.
Różne zagadnienia
Zmiany ingerujące w kompatybilność
Jednym z głównych skutków tego projektu jest to, że System.IntPtr
i System.UIntPtr
uzyskują pewne wbudowane operatory (konwersje, operatory jednoargumentowe i binarne).
Należą do nich operatory checked
, co oznacza, że następujące operatory na tych typach będą teraz zgłaszane podczas przepełnienia:
IntPtr + int
IntPtr - int
IntPtr -> int
long -> IntPtr
void* -> IntPtr
Kodowanie metadanych
Ten projekt oznacza, że nint
i nuint
można po prostu emitować jako System.IntPtr
i System.UIntPtr
, bez użycia System.Runtime.CompilerServices.NativeIntegerAttribute
.
Podobnie podczas ładowania metadanych można zignorować NativeIntegerAttribute
.
C# feature specifications