Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
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 .
Kwestia związana z mistrzem: https://github.com/dotnet/csharplang/issues/6065
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