Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz 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, ulongi 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,decimallubbool. - 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
sbytedoshort,int,nint,long,float,doublelubdecimal. - Z
bytedoshort,ushort,int,uint,nint,nuint,long,ulong,floatdoublelubdecimal. - Od
shortdoint,nint,long,float,doublelubdecimal. - Z
ushortdoint,uint,nint,nuint,long,ulong,float,doublelubdecimal. - Od
intdonint,long,float,doublelubdecimal. - Od
uintdonuint,long,ulong,float,doublelubdecimal. -
Od
nintdolong,float,doublelubdecimal. -
Od
nuintdoulong,float,doublelubdecimal. - Z
longdofloat,doublelubdecimal. - Z
ulongdofloat,doublelubdecimal. - Od
chardoushort,int,uint,nint,nuint,long,ulong,float,doublelubdecimal. - Z
floatdodouble.
[...]
10.2.11 Niejawne konwersje wyrażeń stałych
Niejawna konwersja wyrażenia stałego zezwala na następujące konwersje:
-
constant_expression typu
intmożna przekonwertować na typsbyte,byte,short,ushort,uint,nint,nuintlubulong, 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
sbytedobyte,ushort,uint,nuint,ulonglubchar. - Z
bytedosbytelubchar. - Od
shortdosbyte,byte,ushort,uint,nuint,ulonglubchar. - Z
ushortdosbyte,byte,shortlubchar. - Z
intdosbyte,byte,short,ushort,uint,nuint,ulonglubchar. - Od
uintdosbyte,byte,short,ushort,int,nintlubchar. - Od
longdosbyte,byte,short,ushort,int,uint,nint,nuint,ulonglubchar. -
Od
nintdosbyte,byte,short,ushort,int,uint,nuint,ulonglubchar. -
Od
nuintdosbyte,byte,short,ushort,int,uint,nint,longlubchar. - Od
ulongdosbyte,byte,short,ushort,int,uint,nint,nuint,longlubchar. - Z
chardosbyte,bytelubshort. - Z
floatdosbyte,byte,short,ushort,int,uint,nint,nuint,long,ulong,charlubdecimal. - Od
doubledosbyte,byte,short,ushort,int,uint,nint,nuint,long,ulong,char,floatlubdecimal. - Od
decimaldosbyte,byte,short,ushort,int,uint,nint,nuint,long,ulong,char,floatlubdouble.
[...]
10.3.3 Jawne konwersje typu wyliczeniowego
Jawne konwersje wyliczenia to:
- Z
sbyte,byte,short,ushort,int,uint,nint,nuint,long,ulong,char,float,doublelubdecimaldo dowolnego enum_type. - Od dowolnego enum_type do
sbyte,byte,short,ushort,int,uint,nint,nuint,long,ulong,char,float,doublelubdecimal. - 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, longlub 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, longlub 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, decimali 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, decimali 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, decimali 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
>>zmieniaxw prawo przez kilka bitów obliczonych zgodnie z poniższym opisem.Gdy
xjest typuint,nintlublong, bity o niskiej kolejnościxsą odrzucane, pozostałe bity są przesunięte w prawo, a puste pozycje bitów o wysokiej kolejności są ustawione na zero, jeślixjest nie ujemna i ustawiona na jedną, jeślixjest ujemna.Gdy
xjest typuuint,nuintlubulong, bity o niskiej kolejnościxsą 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
xjestnintlubnuint, liczba zmian jest podawana przez pięć bitów o niskiej kolejnościcountna platformie 32-bitowej lub sześć bitów niższej kolejnościcountna 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, ulonglub 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,,longlubulongdo dowolnego pointer_type. - Z dowolnego pointer_type do
sbyte,byte,short,ushort,int,uint,nint,nuint,longlubulong.
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,longlub 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,longlub 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 + intIntPtr - intIntPtr -> intlong -> IntPtrvoid* -> 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