Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Hinweis
Dieser Artikel ist eine Feature-Spezifikation. Die Spezifikation dient als Designdokument für das Feature. Es enthält vorgeschlagene Spezifikationsänderungen sowie Informationen, die während des Entwurfs und der Entwicklung des Features erforderlich sind. Diese Artikel werden veröffentlicht, bis die vorgeschlagenen Spezifikationsänderungen abgeschlossen und in die aktuelle ECMA-Spezifikation aufgenommen werden.
Es kann einige Abweichungen zwischen der Feature-Spezifikation und der abgeschlossenen Implementierung geben. Diese Unterschiede werden in den relevanten Anmerkungen zum Language Design Meeting (LDM) erfasst.
Weitere Informationen zur Einführung von Funktionen in den C#-Sprachstandard finden Sie im Artikel zu den Spezifikationen.
Champion-Problem: https://github.com/dotnet/csharplang/issues/6065
Zusammenfassung
Dies ist eine Änderung der ursprünglichen nativen Ganzzahlfunktion (Spezifikation), in der sich die nint/nuint-Typen von den zugrunde liegenden Typen System.IntPtr/System.UIntPtr unterschieden haben.
Kurz gesagt behandeln wir nint/nuint als einfache Typenaliase für System.IntPtr/System.UIntPtr, wie bei int in Bezug auf System.Int32. Das Laufzeitfunktions-Flag System.Runtime.CompilerServices.RuntimeFeature.NumericIntPtr löst dieses neue Verhalten aus.
Design
8.3.5 Einfache Typen
C# stellt eine Reihe vordefinierter struct-Typen bereit, die einfache Typen genannt werden. Die einfachen Typen werden durch Schlüsselwörter identifiziert. Diese Schlüsselwörter sind jedoch einfach Aliase für vordefinierte struct-Typen im System-Namespace, wie in der folgenden Tabelle beschrieben.
| Schlüsselwort | Aliastyp |
|---|---|
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 Integrale Typen
C# unterstützt elf integrale Typen: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong und char. [...]
8.8 Nicht verwaltete Typen
Anders ausgedrückt bedeutet dies, dass es sich bei einem unmanaged_type um einen der folgenden Typen handelt:
-
sbyte,byte,short,ushort,int,uint, ,nint,nuint,,long,ulong,char,float,double,decimaloderbool. - Ein enum_type.
- Ein benutzerdefinierter struct_type, der nicht konstruiert ist und nur unmanaged_type-Felder enthält.
- In unsicherem Code ein .
10.2.3 Implizite numerische Konvertierungen
Die impliziten numerischen Konvertierungen sind:
- Von
sbyteinshort,int,nint,long,float,doubleoderdecimal. - Von
byteinshort,ushort,int,uint,nint,nuint,long,ulong,float,doubleoderdecimal. - Von
shortinint,nint,long,float,doubleoderdecimal. - Von
ushortinint,uint,nint,nuint,long,ulong,float,doubleoderdecimal. - Von
intinnint,long,float,doubleoderdecimal. - Von
uintinnuint,long,ulong,float,doubleoderdecimal. -
Von
nintinlong,float,doubleoderdecimal. -
Von
nuintinulong,float,doubleoderdecimal. - Von
longinfloat,doubleoderdecimal. - Von
ulonginfloat,doubleoderdecimal. - Von
charinushort,int,uint,nint,nuint,long,ulong,float,doubleoderdecimal. - Von
floatbisdouble.
[...]
10.2.11 Implizite Konvertierungen von Konstantenausdrücken
Eine implizite Konvertierung von Konstantenausdrücken ermöglicht die folgenden Konvertierungen:
- Ein constant_expression mit dem Typ
intkann in den Typsbyte,byte,short,ushort,uint,nint,nuintoderulongkonvertiert werden, wenn der Wert von constant_expression innerhalb des Bereichs des Zieltyps liegt. [...]
10.3.2 Explizite numerische Konvertierungen
Die expliziten numerischen Konvertierungen sind Konvertierungen aus einem numeric_type in einen anderen numeric_type, für die noch keine implizite numerische Konvertierung vorhanden ist:
- Von
sbyteinbyte,ushort,uint,nuint,ulongoderchar. - Von
byteinsbyteoderchar. - Von
shortinsbyte,byte,ushort,uint,nuint,ulongoderchar. - Von
ushortinsbyte,byte,shortoderchar. - Von
intinsbyte,byte,short,ushort,uint,nuint,ulongoderchar. - Von
uintinsbyte,byte,short,ushort,int,nintoderchar. - Von
longinsbyte,byte,short,ushort,int,uint,nint,nuint,ulongoderchar. -
Von
nintinsbyte,byte,short,ushort,int,uint,nuint,ulongoderchar. -
Von
nuintinsbyte,byte,short,ushort,int,uint,nint,longoderchar. - Von
ulonginsbyte,byte,short,ushort,int,uint,nint,nuint,longoderchar. - Von
charinsbyte,byteodershort. - Von
floatinsbyte,byte,short,ushort,int,uint,nint,nuint,long,ulong,charoderdecimal. - Von
doubleinsbyte,byte,short,ushort,int,uint,nint,nuint,long,ulong,char,floatoderdecimal. - Von
decimalinsbyte,byte,short,ushort,int,uint,nint,nuint,long,ulong,char,floatoderdouble.
[...]
10.3.3 Explizite Enumerationskonvertierungen
Die expliziten Enumerationskonvertierungen sind:
- Von
sbyte,byte,short,ushort,int,uint,nint,nuint,long,ulong,char,float,doubleoderdecimalin einen enum_type. - Von einem enum_type in
sbyte,byte,short,ushort,int,uint,nint,nuint,long,ulong,char,float,doubleoderdecimal. - Von einem enum_type in einen anderen enum_type.
12.6.4.7 Besseres Konvertierungsziel
Bei den beiden Typen T₁ und T₂ ist T₁ ein besseres Konvertierungsziel als T₂, wenn eine der folgenden Bedingungen erfüllt ist:
- Eine implizite Konversion von
T₁nachT₂existiert und keine implizite Konversion vonT₂nachT₁existiert -
T₁istTask<S₁>,T₂istTask<S₂>, undS₁ist ein besseres Konvertierungsziel alsS₂ -
T₁istS₁oderS₁?, wobeiS₁ein Integraltypen mit Vorzeichen ist, undT₂istS₂oderS₂?, wobeiS₂ein Integraltypen ohne Vorzeichen ist. Insbesondere: [...]
12.8.12 Elementzugriff
[...] Die Anzahl der Ausdrücke in der argument_list muss dem Rang des array_type entsprechen und jeder Ausdruck muss vom Typ int, uint, nint, nuint, long oder ulong, sein oder implizit in einen oder mehrere dieser Typen konvertierbar sein.
11.8.12.2 Arrayzugriff
[...] Die Anzahl der Ausdrücke in der argument_list muss dem Rang des array_type entsprechen und jeder Ausdruck muss vom Typ int, uint, nint, nuint, long oder ulong, sein oder implizit in einen oder mehrere dieser Typen konvertierbar sein.
[...] Die Laufzeitverarbeitung eines Arrayzugriffs der Form P[A], wobei P ein primary_no_array_creation_expression eines array_type ist und A eine argument_list ist, umfasst die folgenden Schritte: [...]
- Die Indexausdrücke der argument_list werden von links nach rechts ausgewertet. Nach der Auswertung jedes Indexausdrucks erfolgt eine implizite Konvertierung in einen der folgenden Typen:
int,uint,nint,nuint,long,ulong. Der erste Typ in dieser Liste, für den eine implizite Konversion existiert, wird ausgewählt. [...]
12.8.16 Inkrementierungs- und Dekrementierungsoperatoren in Postfixnotation
Die unäre Operatorüberladungsauflösung wird angewendet, um eine bestimmte Operatorimplementierung auszuwählen. Es gibt vordefinierte ++- und ---Operatoren für die folgenden Typen: sbyte, byte, short, ushort, int, uint, nint, nuint,long, ulong, char, float, double, decimal und alle Enumerationstypen.
12.9.2 Unärer Plus-Operator
Die vordefinierten unären Plus-Operatoren sind:
...
nint operator +(nint x);
nuint operator +(nuint x);
12.9.3 Unärer Minus-Operator
Die vordefinierten unären Minus-Operatoren sind:
Ganzzahlnegation:
... nint operator –(nint x);
12.8.16 Inkrementierungs- und Dekrementierungsoperatoren in Postfixnotation
Es gibt vordefinierte ++- und ---Operatoren für die folgenden Typen: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal und alle Enumerationstypen.
11.7.19 Ausdrücke für Standardwerte
Darüber hinaus ist ein default_value_expression ein konstanter Ausdruck, wenn der Typ einer der folgenden Werttypen ist: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal, bool, oder ein Enumerationstyp.
12.9.5 Bitweiser Komplement-Operator
Die vordefinierten bitweisen Komplement-Operatoren sind:
...
nint operator ~(nint x);
nuint operator ~(nuint x);
12.9.6 Inkrementierungs- und Dekrementierungsoperatoren in Präfixnotation
Es gibt vordefinierte ++- und ---Operatoren für die folgenden Typen: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal und alle Enumerationstypen.
12.10 Arithmetische Operatoren
12.10.2 Multiplikations-Operator
Die vordefinierten Multiplikationsoperatoren sind im Folgenden aufgeführt. Die Operatoren berechnen alle das Produkt von x und y.
Ganzzahlmultiplikation:
... nint operator *(nint x, nint y); nuint operator *(nuint x, nuint y);
12.10.3 Divisions-Operator
Die vordefinierten Divisionsoperatoren sind unten aufgeführt. Alle Operatoren berechnen den Quotienten von x und y.
Ganzzahldivision:
... nint operator /(nint x, nint y); nuint operator /(nuint x, nuint y);
12.10.4 Rest-Operator
Die vordefinierten Rest-Operatoren werden unten aufgeführt. Alle Operatoren berechnen den Rest der Division zwischen x und y.
Ganzzahlrest:
... nint operator %(nint x, nint y); nuint operator %(nuint x, nuint y);
12.10.5 Additions-Operator
Ganzzahladdition:
... nint operator +(nint x, nint y); nuint operator +(nuint x, nuint y);
12.10.6 Subtraktions-Operator
Ganzzahlsubtraktion:
... nint operator –(nint x, nint y); nuint operator –(nuint x, nuint y);
12.11 Schiebeoperatoren
Die vordefinierten Verschiebungsoperatoren sind unten aufgeführt.
Nach links verschieben:
... nint operator <<(nint x, int count); nuint operator <<(nuint x, int count);Nach rechts verschieben:
... nint operator >>(nint x, int count); nuint operator >>(nuint x, int count);Der
>>-Operator verschiebtxum eine Anzahl von Bits nach rechts, die wie unten beschrieben berechnet wird.Wenn
xvom Typint,nintoderlongist, werden die Bits mit niedriger Reihenfolge vonxverworfen, die verbleibenden Bits werden nach rechts verschoben, und die leeren Bitpositionen in hoher Reihenfolge werden auf Null festgelegt, wennxnicht negativ ist, und auf Eins festgelegt, wennxnegativ ist.Wenn
xvom Typuint,nuintoderulongist, werden die niederwertigsten Bits vonxverworfen, die verbleibenden Bits werden nach rechts verschoben, und die höchstwertigen leeren Bitpositionen werden auf Null gesetzt.Vorzeichenlose Rechtsverschiebung:
... nint operator >>>(nint x, int count); nuint operator >>>(nuint x, int count);
Für die vordefinierten Operatoren wird die Anzahl der zu verschiebenden Bits wie folgt berechnet: [...]
- Wenn der Typ von
xnintodernuintist, wird der Verschiebungswert durch die niederwertigen fünf Bits voncountauf einer 32-Bit-Plattform oder die niederwertigen sechs Bits voncountauf einer 64-Bit-Plattform angegeben.
12.12 Relationale und Typtest-Operatoren
12.12.2 Ganzzahlvergleichs-Operatoren
Die vordefinierten ganzzahligen Vergleichsoperatoren sind:
...
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 Logische Operatoren
12.12.2 Logische Ganzzahl-Operatoren
Die vordefinierten ganzzahligen logischen Operatoren sind:
...
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 Konstante Ausdrücke
Ein konstanter Ausdruck kann ein Werttyp oder ein Referenztyp sein. Wenn ein Konstantenausdruck ein Werttyp ist, muss es sich um einen der folgenden Typen handeln: sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal, bool, oder einen Enumerationstyp.
[...]
Eine implizite Konversion von konstanten Ausdrücken erlaubt die Konvertierung eines konstanten Ausdrucks vom Typ int in sbyte, byte, short, ushort, uint, nint, nuint, oder ulong, sofern der Wert des konstanten Ausdrucks im Bereich des Zieltyps liegt.
17.4 Zugriff auf Arrayelemente
Auf Arrayelemente wird mithilfe von element_access Ausdrücken im Format A[I₁, I₂, ..., Iₓ] zugegriffen, wobei A ein Ausdruck eines Arraytyps ist und Iₑ jeweils ein Ausdruck mit dem Typ int, uint, nint, nuint,long oder ulong ist oder implizit in einen oder mehrere dieser Typen konvertiert werden kann. Das Ergebnis eines Zugriffs auf Arrayelemente ist eine Variable, und zwar das Arrayelement, das durch die Indizes ausgewählt wurde.
23.5 Zeigerkonvertierungen
23.5.1 Allgemein
[...]
Darüber hinaus wird der Satz verfügbarer expliziter Konvertierungen in einem unsicheren Kontext erweitert, sodass er die folgenden expliziten Zeigerkonvertierungen einschließt:
- Von einem pointer_type in einen anderen pointer_type.
- Von
sbyte,byte,short,ushort,int,uint,nint,nuint,longoderulongin einen pointer_type. - Von einem pointer_type in
sbyte,byte,short,ushort,int,uint,nint,nuint,longoderulong.
23.6.5. Zeigerelementzugriff
[...] Bei einem Zeigerelementzugriff auf das Formular P[E] muss P ein Ausdruck eines anderen Zeigertyps als void* sein und E muss ein Ausdruck sein, der implizit in int, uint, nint, nuint,long oder ulong konvertiert werden kann.
23.6.7 Zeigerarithmetik
In einem unsicheren Kontext können der +-Operator und der –-Operator auf Werte aller Zeigertypen angewendet werden, mit Ausnahme von void*. Daher werden für jeden Zeigertyp T* die folgenden Operatoren implizit definiert:
[...]
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);
Auf der Basis eines Ausdrucks P eines Zeigertyps T* und eines Ausdrucks N mit dem Typ int, uint, nint, nuint,long oder ulong berechnen die Ausdrücke P + N und N + P den Zeigerwert des Typs T*, der das Ergebnis der Addition von N * sizeof(T) zu der Adresse ist, die von P angegeben wird. Ähnlich berechnet der Ausdruck P – N den Zeigerwert des Typs T*, der das Ergebnis der Subtraktion von N * sizeof(T) von der Adresse ist, die von P angegeben wird.
Verschiedene Überlegungen
Wichtige Änderungen
Eine der wichtigsten Auswirkungen dieses Designs ist, dass System.IntPtr und System.UIntPtr einige integrierte Operatoren (Konvertierungen, unär und binär) erhalten.
Dazu gehören checked-Operatoren, was bedeutet, dass die folgenden Operatoren für diese Typen jetzt im Überlauf ausgelöst werden:
IntPtr + intIntPtr - intIntPtr -> intlong -> IntPtrvoid* -> IntPtr
Codierung von Metadaten
Dieses Design bedeutet, dass nint und nuint einfach als System.IntPtr und System.UIntPtr ohne Verwendung von System.Runtime.CompilerServices.NativeIntegerAttribute ausgegeben werden können.
Beim Laden von Metadaten kann NativeIntegerAttribute jetzt ignoriert werden.
C# feature specifications