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.
Anmerkung
Dieser Artikel ist eine Featurespezifikation. 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 Featurespezifikation und der abgeschlossenen Implementierung geben. Diese Unterschiede werden in den entsprechenden Hinweisen zum Language Design Meeting (LDM) erfasst.
Weitere Informationen zum Prozess für die Aufnahme von Funktions-Speclets in den C#-Sprachstandard finden Sie im Artikel zu den Spezifikationen.
Champion Issue: https://github.com/dotnet/csharplang/issues/4682
Zusammenfassung
Ein vorzeichenloser Rechtsverschiebungs-Operator wird von C# als integrierter Operator (für primitive Integraltypen) und als benutzerdefinierter Operator unterstützt.
Motivation
Bei der Arbeit mit vorzeichenbehafteten Integralwerten ist es nicht ungewöhnlich, dass Sie Bits nach rechts verschieben müssen, ohne das Bit hoher Ordnung bei jeder Verschiebung zu replizieren. Während dies bei primitiven Integraltypen mit einem regulären Verschiebungs-Operator erreicht werden kann, ist vor dem Verschiebungsvorgang ein Cast in einen vorzeichenlosen Typ und danach ein Cast-Back erforderlich. Im Zusammenhang mit den generischen mathematischen Schnittstellen, die die Bibliotheken planen, ist dies potenziell problematischer, da der Typ nicht unbedingt ein vorzeichenloses Gegenstück haben muss, das definiert oder dem generischen mathematischen Code im Voraus bekannt ist, ein Algorithmus jedoch auf die Fähigkeit angewiesen sein könnte, einen vorzeichenlosen Right-Shift-Operator durchzuführen.
Detailliertes Design
Operatoren und Trennzeichen
Abschnitt §6.4.6 wird geändert, um den >>>-Operator aufzunehmen – den Rechtsverschiebungs-Operator ohne Vorzeichen:
unsigned_right_shift
: '>>>'
;
unsigned_right_shift_assignment
: '>>>='
;
Zwischen den Token in den Produktionen unsigned_right_shift und unsigned_right_shift_assignment sind keine Zeichen (auch keine Leerzeichen) zugelassen. Diese Produktionen werden speziell behandelt, um die korrekte Behandlung von typ_parameter_list zu ermöglichen.
Schiebeoperatoren
Abschnitt §12.11 wird geändert, um den >>>-Operator (den Rechtsverschiebungs-Operator ohne Vorzeichen) aufzunehmen:
Die Operatoren <<, >> und >>> werden zum Ausführen von Bitverschiebungsvorgängen verwendet.
shift_expression
: additive_expression
| shift_expression '<<' additive_expression
| shift_expression right_shift additive_expression
| shift_expression unsigned_right_shift additive_expression
;
Für einen Vorgang der Form x << count, x >> count oder x >>> count wird die Überladungsauflösung für binäre Operatoren (§12.4.5) angewendet, um eine bestimmte Implementierung des Operators auszuwählen. Die Operanden werden in die Parametertypen des ausgewählten Operators konvertiert, und der Typ des Ergebnisses ist der Rückgabetyp des Operators.
Die vordefinierten vorzeichenlosen Verschiebungsoperatoren unterstützen dieselbe Reihe von Signaturen, die vordefinierte vorzeichenbehaftete Verschiebungsoperatoren in der aktuellen Implementierung unterstützen.
Nach rechts verschieben:
int operator >>>(int x, int count); uint operator >>>(uint x, int count); long operator >>>(long x, int count); ulong operator >>>(ulong x, int count); 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.Die niederwertigen Bits von
xwerden verworfen. Die verbleibenden Bits werden nach rechts verschoben und die höherwertigen leeren Bitpositionen werden auf Null festgelegt.
Für die vordefinierten Operatoren wird die Anzahl der zu verschiebenden Bits wie folgt berechnet:
- Wenn der Typ von
xintoderuintist, wird die Anzahl der Verschiebungen durch die niederwertigen fünf Bits voncountbestimmt. Mit anderen Worten, die Anzahl der Verschiebungen wird auscount & 0x1Fberechnet. - Wenn der Typ von
xlongoderulongist, wird die Anzahl der Verschiebungen durch die niederwertigen sechs Bits voncountbestimmt. Mit anderen Worten, die Anzahl der Verschiebungen wird auscount & 0x3Fberechnet.
Wenn die resultierende Schichtanzahl null ist, geben die Schichtoperatoren einfach den Wert von xzurück.
Verschiebungsvorgänge führen nie zu Überläufen und liefern in checked- und unchecked-Kontexten die gleichen Ergebnisse.
Assignment operators (Zuweisungsoperatoren)
Abschnitt §12.21 wird geändert, um unsigned_right_shift_assignment wie folgt aufzunehmen:
assignment_operator
: '='
| '+='
| '-='
| '*='
| '/='
| '%='
| '&='
| '|='
| '^='
| '<<='
| right_shift_assignment
| unsigned_right_shift_assignment
;
Ganzzahlige Typen
Der Abschnitt über die integralen Typen §8.3.6 wird angepasst, um Informationen über den >>>-Operator zu integrieren. Der entsprechende Aufzählungspunkt lautet wie folgt:
- Für die Binär-Operatoren
<<,>>und>>>wird der linke Operand in den TypTkonvertiert, wobeiTder erste vonint,uint,longundulongist, die alle möglichen Werte des Operanden vollständig repräsentieren können. Der Vorgang wird dann mit der Genauigkeit des TypsTdurchgeführt, und der Typ des Ergebnisses istT.
Konstante Ausdrücke
Der Operator >>> wird der Menge der in konstanten Ausdrücken zulässigen Konstrukte unter §12.23 hinzugefügt.
Überladen von Operatoren
Der Operator >>> wird in die Menge der überladbaren binären Operatoren unter §12.4.3 aufgenommen.
„Lifted“ Operatoren
Der Operator >>> wird in die Menge der binären Operatoren aufgenommen, die in §12.4.8 eine Lifted-Form zulassen.
Operatorrangfolge und Assoziativität
Abschnitt §12.4.2 wird geändert, um den >>>-Operator zur Kategorie „Verschiebung“ und den >>>=-Operator zur Kategorie „Zuweisung und Lambda-Ausdruck“ hinzuzufügen.
Grammatische Mehrdeutigkeiten
Der >>>-Operator unterliegt den gleichen grammatikalischen Mehrdeutigkeiten, die in §6.2.5 als regulärer >>-Operator beschrieben sind.
Operatoren
Der Abschnitt §15.10 wird geändert, um den >>>-Operator aufzunehmen.
overloadable_binary_operator
: '+' | '-' | '*' | '/' | '%' | '&' | '|' | '^' | '<<'
| right_shift | unsigned_right_shift | '==' | '!=' | '>' | '<' | '>=' | '<='
;
Binäre Operatoren
Die Signatur eines >>>-Betreibers unterliegt den gleichen Regeln wie die bei §15.10.3 für die Signatur eines >>-Betreibers.
Metadatenname
Abschnitt „I.10.3.2 Binäre Operatoren“ von ECMA-335 hat bereits den Namen für einen Rechtsverschiebungs-Operator ohne Vorzeichen reserviert – op_UnsignedRightShift.
Linq-Ausdrucksbäume
Der >>>-Operator wird in Linq-Ausdrucksbäumen nicht unterstützt, da die Semantik der vordefinierten >>>-Operatoren für vorzeichenbehaftete Typen nicht korrekt dargestellt werden kann, ohne Konvertierungen in einen vorzeichenlosen Typ und zurück hinzuzufügen. Weitere Informationen finden Sie unter https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator.
Dynamische Bindung
Es sieht so aus, als ob die dynamische Bindung Werte des Enums System.Linq.Expressions.ExpressionType verwendet, um die Art des binären Operators an den Laufzeit-Binder zu übermitteln. Da es kein Element gibt, das speziell einen Rechtsverschiebungs-Operator ohne Vorzeichen repräsentiert, wird die dynamische Bindung für den >>>-Operator nicht unterstützt, und der Abschnitt über statische und dynamische Bindung (§12.3) wird entsprechend geändert.
Nachteile
Alternativen
Linq-Ausdrucksbäume
Der >>>-Operator wird in Linq-Ausdrucksbäumen unterstützt.
- Für einen benutzerdefinierten Operator wird ein BinaryExpression-Knoten erstellt, der auf die Operatormethode zeigt.
- Für vordefinierte Operatoren
- Wenn der erste Operand ein Typ mit Vorzeichen ist, wird ein BinaryExpression-Knoten erstellt.
- Wenn der erste Operand ein Typ mit Vorzeichen ist, werden eine Konvertierung für den ersten Operanden in einen Typ ohne Vorzeichen hinzugefügt, ein BinaryExpression-Knoten erstellt und eine Konvertierung für das Ergebnis zurück in den Typ mit Vorzeichen hinzugefügt.
Zum Beispiel:
Expression<System.Func<int, int, int>> z = (x, y) => x >>> y; // (x, y) => Convert((Convert(x, UInt32) >> y), Int32)
Resolution:
Abgelehnt, siehe https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator für weitere Informationen.
Ungelöste Fragen
Designbesprechungen
https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md
C# feature specifications