Ereignisse
Erstellen von KI-Apps und Agents
17. März, 21 Uhr - 21. März, 10 Uhr
Nehmen Sie an der Meetup-Serie teil, um skalierbare KI-Lösungen basierend auf realen Anwendungsfällen mit Mitentwicklern und Experten zu erstellen.
Jetzt registrierenDieser Browser wird nicht mehr unterstützt.
Führen Sie ein Upgrade auf Microsoft Edge aus, um die neuesten Funktionen, Sicherheitsupdates und technischen Support zu nutzen.
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
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.
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 |
[...]
C# unterstützt elf integrale Typen: sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
und char
. [...]
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
, decimal
oder bool
.Die impliziten numerischen Konvertierungen sind:
sbyte
in short
, int
, nint
, long
, float
, double
oder decimal
.byte
in short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
, float
, double
oder decimal
.short
in int
, nint
, long
, float
, double
oder decimal
.ushort
in int
, uint
, nint
, nuint
, long
, ulong
, float
, double
oder decimal
.int
in nint
, long
, float
, double
oder decimal
.uint
in nuint
, long
, ulong
, float
, double
oder decimal
.nint
in long
, float
, double
oder decimal
.nuint
in ulong
, float
, double
oder decimal
.long
in float
, double
oder decimal
.ulong
in float
, double
oder decimal
.char
in ushort
, int
, uint
, nint
, nuint
, long
, ulong
, float
, double
oder decimal
.float
bis double
.[...]
Eine implizite Konvertierung von Konstantenausdrücken ermöglicht die folgenden Konvertierungen:
int
kann in den Typ sbyte
, byte
, short
, ushort
, uint
, nint
, nuint
oder ulong
konvertiert werden, wenn der Wert von constant_expression innerhalb des Bereichs des Zieltyps liegt.
[...]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:
sbyte
in byte
, ushort
, uint
, nuint
, ulong
oder char
.byte
in sbyte
oder char
.short
in sbyte
, byte
, ushort
, uint
, nuint
, ulong
oder char
.ushort
in sbyte
, byte
, short
oder char
.int
in sbyte
, byte
, short
, ushort
, uint
, nuint
, ulong
oder char
.uint
in sbyte
, byte
, short
, ushort
, int
, nint
oder char
.long
in sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, ulong
oder char
.nint
in sbyte
, byte
, short
, ushort
, int
, uint
, nuint
, ulong
oder char
.nuint
in sbyte
, byte
, short
, ushort
, int
, uint
, nint
, long
oder char
.ulong
in sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
oder char
.char
in sbyte
, byte
oder short
.float
in sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
, char
oder decimal
.double
in sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
, char
, float
oder decimal
.decimal
in sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
, char
, float
oder double
.[...]
Die expliziten Enumerationskonvertierungen sind:
sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
, char
, float
, double
oder decimal
in einen enum_type.sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
, long
, ulong
, char
, float
, double
oder decimal
.Bei den beiden Typen T₁
und T₂
ist T₁
ein besseres Konvertierungsziel als T₂
, wenn eine der folgenden Bedingungen erfüllt ist:
T₁
nach T₂
existiert und keine implizite Konversion von T₂
nach T₁
existiertT₁
ist Task<S₁>
, T₂
ist Task<S₂>
, und S₁
ist ein besseres Konvertierungsziel als S₂
T₁
ist S₁
oder S₁?
, wobei S₁
ein Integraltypen mit Vorzeichen ist, und T₂
ist S₂
oder S₂?
, wobei S₂
ein Integraltypen ohne Vorzeichen ist. Insbesondere: [...][...] 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 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: [...]
int
, uint
, nint
, nuint
, long
, ulong
. Der erste Typ in dieser Liste, für den eine implizite Konversion existiert, wird ausgewählt. [...]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.
Die vordefinierten unären Plus-Operatoren sind:
...
nint operator +(nint x);
nuint operator +(nuint x);
Die vordefinierten unären Minus-Operatoren sind:
Ganzzahlnegation:
...
nint operator –(nint x);
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.
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.
Die vordefinierten bitweisen Komplement-Operatoren sind:
...
nint operator ~(nint x);
nuint operator ~(nuint x);
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.
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);
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);
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);
Ganzzahladdition:
...
nint operator +(nint x, nint y);
nuint operator +(nuint x, nuint y);
Ganzzahlsubtraktion:
...
nint operator –(nint x, nint y);
nuint operator –(nuint x, nuint y);
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 verschiebt x
um eine Anzahl von Bits nach rechts, die wie unten beschrieben berechnet wird.
Wenn x
vom Typ int
, nint
oder long
ist, werden die Bits mit niedriger Reihenfolge von x
verworfen, die verbleibenden Bits werden nach rechts verschoben, und die leeren Bitpositionen in hoher Reihenfolge werden auf Null festgelegt, wenn x
nicht negativ ist, und auf Eins festgelegt, wenn x
negativ ist.
Wenn x
vom Typ uint
, nuint
oder ulong
ist, werden die niederwertigsten Bits von x
verworfen, 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: [...]
x
nint
oder nuint
ist, wird der Verschiebungswert durch die niederwertigen fünf Bits von count
auf einer 32-Bit-Plattform oder die niederwertigen sechs Bits von count
auf einer 64-Bit-Plattform angegeben.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);
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);
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.
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.
[...]
Darüber hinaus wird der Satz verfügbarer expliziter Konvertierungen in einem unsicheren Kontext erweitert, sodass er die folgenden expliziten Zeigerkonvertierungen einschließt:
sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
,long
oder ulong
in einen pointer_type.sbyte
, byte
, short
, ushort
, int
, uint
, nint
, nuint
,long
oder ulong
.[...] 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.
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.
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 + int
IntPtr - int
IntPtr -> int
long -> IntPtr
void* -> IntPtr
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.
Feedback zu C# feature specifications
C# feature specifications ist ein Open Source-Projekt. Wählen Sie einen Link aus, um Feedback zu geben:
Ereignisse
Erstellen von KI-Apps und Agents
17. März, 21 Uhr - 21. März, 10 Uhr
Nehmen Sie an der Meetup-Serie teil, um skalierbare KI-Lösungen basierend auf realen Anwendungsfällen mit Mitentwicklern und Experten zu erstellen.
Jetzt registrieren