Delen via


Ongesigneerde rechtsverschuivingsoperator

Notitie

Dit artikel is een functiespecificatie. De specificatie fungeert als het ontwerpdocument voor de functie. Het bevat voorgestelde specificatiewijzigingen, samen met informatie die nodig is tijdens het ontwerp en de ontwikkeling van de functie. Deze artikelen worden gepubliceerd totdat de voorgestelde specificaties zijn voltooid en opgenomen in de huidige ECMA-specificatie.

Er kunnen enkele verschillen zijn tussen de functiespecificatie en de voltooide implementatie. Deze verschillen worden vastgelegd in de relevante LDM-notities (Language Design Meeting) .

Meer informatie over het proces voor het aannemen van functiespeclets in de C#-taalstandaard vindt u in het artikel over de specificaties.

Probleem met kampioen: https://github.com/dotnet/csharplang/issues/4682

Samenvatting

Een niet-ondertekende rechter shift-operator wordt door C# ondersteund als een ingebouwde operator (voor primitieve integrale typen) en als door de gebruiker gedefinieerde operator.

Motivatie

Wanneer u met gesigneerde gehele waarde werkt, is het niet ongebruikelijk dat u bits naar rechts moet verplaatsen zonder de hoogste orde bit bij elke verschuiving te repliceren. Hoewel dit kan worden bereikt voor primitieve integrale typen met een reguliere verschuivingsoperator, is een cast naar een ongetekend type vóór de verschuivingsbewerking en een cast terug daarna vereist. In de context van de algemene wiskundige interfaces die de bibliotheken beschikbaar willen stellen, kan dit problematisch zijn omdat het type mogelijk geen ongetekende tegenhanger heeft, of deze niet vooraf bekend is bij de algemene wiskundige code, terwijl een algoritme afhankelijk kan zijn van de mogelijkheid om een ongetekende rechtsverschuiving uit te voeren.

Gedetailleerd ontwerp

Operatoren en leestekens

Sectie §6.4.6 wordt aangepast om >>> operator - de niet-ondertekende rechterdienstoperator op te nemen:

unsigned_right_shift
    : '>>>'
    ;

unsigned_right_shift_assignment
    : '>>>='
    ;

Er zijn geen tekens van welke aard dan ook toegestaan (zelfs geen witruimte) tussen de tokens in unsigned_right_shift en unsigned_right_shift_assignment producties. Deze producties worden speciaal behandeld om de juiste verwerking van type_parameter_lists mogelijk te maken.

Shiftoperatoren

Sectie §12.11 wordt aangepast om >>> operator - de niet-ondertekende rechterdienstoperator op te nemen:

De operators <<, >> en >>> worden gebruikt om bitverschuifbewerkingen uit te voeren.

shift_expression
    : additive_expression
    | shift_expression '<<' additive_expression
    | shift_expression right_shift additive_expression
    | shift_expression unsigned_right_shift additive_expression
    ;

Voor een werking van het formulier x << count of x >> count of x >>> countwordt overbelastingsresolutie van binaire operatoren (§12.4.5) toegepast om een specifieke operator-implementatie te selecteren. De operanden worden geconverteerd naar de parametertypen van de geselecteerde operator en het type van het resultaat is het retourtype van de operator.

De vooraf gedefinieerde niet-ondertekende shiftoperators ondersteunen dezelfde set handtekeningen die vooraf gedefinieerde ondertekende shiftoperators vandaag ondersteunen in de huidige implementatie.

  • Naar rechts gaan:

    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);
    

    De operator >>> verschuift x naar rechts door een aantal bits dat is berekend, zoals hieronder wordt beschreven.

    De bits met lage volgorde van x worden verwijderd, de resterende bits worden naar rechts verplaatst en de lege bitposities met hoge volgorde worden ingesteld op nul.

Voor de vooraf gedefinieerde operators wordt het aantal bits dat moet worden verplaatst als volgt berekend:

  • Wanneer het type van xint of uintis, wordt het verplaatsingsaantal gegeven door de vijf lage-orde bits van count. Met andere woorden, het aantal diensten wordt berekend op basis van count & 0x1F.
  • Wanneer het type xlong of ulongis, wordt het aantal verschuivingen gegeven door de laag-order zes bits van count. Met andere woorden, het aantal diensten wordt berekend op basis van count & 0x3F.

Als het resulterende aantal diensten nul is, retourneren de shiftoperators gewoon de waarde van x.

Shift-bewerkingen veroorzaken nooit overloop en produceren dezelfde resultaten in checked en unchecked contexten.

Toewijzingsoperatoren

Sectie §12.21 wordt als volgt aangepast om unsigned_right_shift_assignment op te nemen:

assignment_operator
    : '='
    | '+='
    | '-='
    | '*='
    | '/='
    | '%='
    | '&='
    | '|='
    | '^='
    | '<<='
    | right_shift_assignment
    | unsigned_right_shift_assignment
    ;

Integrale typen

De integrale typen-sectie §8.3.6 wordt aangepast om informatie over de >>>-operator op te nemen. Het relevante opsommingsteken is het volgende:

  • Voor de binaire <<, >> en >>> operatoren wordt de linkeroperand geconverteerd naar het type T, waarbij T de eerste is van int, uint, longen ulong die alle mogelijke waarden van de operand volledig kunnen vertegenwoordigen. De bewerking wordt vervolgens uitgevoerd met de precisie van type Ten het type van het resultaat is T.

Constante expressies

Operator >>> wordt toegevoegd aan de set constructies die zijn toegestaan in constante expressies op §12.23.

Overbelasting van operator

Operator >>> wordt toegevoegd aan de set overbelaste binaire operatoren op §12.4.3.

Opgetilde operatoren

Operator >>> wordt toegevoegd aan de set binaire operatoren die een opgeheven formulier toestaan op §12.4.8.

Operatorprioriteit en associativiteit

Sectie §12.4.2 wordt aangepast om >>> operator toe te voegen aan de categorie Shift en >>>= operator aan de categorie Toewijzing en lambda-expressie.

Ambiguïteit grammatica

De operator >>> is onderworpen aan dezelfde ambiguïteiten voor grammatica die worden beschreven in §6.2.5 als een gewone >> operator.

Exploitanten

De §15.10 sectie wordt aangepast om >>> operator op te nemen.

overloadable_binary_operator
    : '+'   | '-'   | '*'   | '/'   | '%'   | '&'   | '|'   | '^'   | '<<'
    | right_shift | unsigned_right_shift | '=='  | '!='  | '>'   | '<'   | '>='  | '<='
    ;

Binaire operatoren

De handtekening van een >>> operator is onderworpen aan dezelfde regels als die in §15.10.3 voor de handtekening van een >> operator.

Naam van metagegevens

Sectie "I.10.3.2 Binaire operators" van ECMA-335 heeft al de naam gereserveerd voor een niet-ondertekende rechter shift-operator - op_UnsignedRightShift.

Linq Expression Trees

De operator >>> wordt niet ondersteund in Linq Expression Trees, omdat de semantiek van vooraf gedefinieerde >>> operators op getekende typen niet nauwkeurig kan worden weergegeven zonder dat er conversies worden toegevoegd naar een ongetekend type en terug. Zie https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator voor meer informatie.

Dynamische binding

Het lijkt erop dat dynamische binding waarden van System.Linq.Expressions.ExpressionType enum gebruikt om het type binaire operator te communiceren met de runtime-binder. Omdat we geen lid hebben dat specifiek een niet-ondertekende right shift-operator vertegenwoordigt, zal dynamische binding voor de >>>-operator niet worden ondersteund en zal de sectie over statische en dynamische binding (§12.3) worden aangepast om dat te weerspiegelen.

Nadelen

Alternatieven

Linq Expression Trees

De operator >>> wordt ondersteund in Linq Expressioin Trees.

  • Voor een door de gebruiker gedefinieerde operator wordt een BinaryExpression-knooppunt gemaakt dat verwijst naar de operatormethode.
  • Voor vooraf gedefinieerde operators
    • wanneer de eerste operand een ansigned type is, wordt er een BinaryExpression-knooppunt gemaakt.
    • wanneer de eerste operand een ondertekend type is, wordt er een conversie voor de eerste operand naar een niet-ondertekend type toegevoegd, wordt er een BinaryExpression-knooppunt gemaakt en wordt de conversie voor het resultaat weer toegevoegd aan het ondertekende type.

Bijvoorbeeld:

Expression<System.Func<int, int, int>> z = (x, y) => x >>> y; // (x, y) => Convert((Convert(x, UInt32) >> y), Int32)

Resolution:

Afgewezen, zie https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator voor meer informatie.

Niet-opgeloste vragen

Ontwerpvergaderingen

https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md