Dela via


Osignerad höger skiftoperator

Not

Den här artikeln är en funktionsspecifikation. Specifikationen fungerar som designdokument för funktionen. Den innehåller föreslagna specifikationsändringar, tillsammans med information som behövs under utformningen och utvecklingen av funktionen. Dessa artiklar publiceras tills de föreslagna specifikationsändringarna har slutförts och införlivats i den aktuella ECMA-specifikationen.

Det kan finnas vissa skillnader mellan funktionsspecifikationen och den slutförda implementeringen. Dessa skillnader samlas in i de relevanta anteckningarna från LDM (Language Design Meeting) .

Du kan läsa mer om processen för att införa funktionsspecifikationer i C#-språkstandarden i artikeln om specifikationerna.

Sammanfattning

En osignerad högerflytt-operator kommer att stödjas av C# både som en inbyggd operator (för primitiva integraltyper) och som en användardefinierad operator.

Motivation

När du arbetar med signerat integralvärde är det inte ovanligt att du behöver flytta bitar rätt utan att replikera den höga orderbiten på varje skift. Även om detta kan uppnås för primära integraltyper med en vanlig skiftoperator, krävs en konvertering till en osignerad typ före skiftoperationen och en konvertering tillbaka efteråt. Inom ramen för de allmänna matematiska gränssnitt som biblioteken planerar att exponera är detta potentiellt mer problematiskt eftersom typen kanske inte behöver ha en osignerad motsvarighet definierad eller känd i förväg av den allmänna matematiska koden, men en algoritm kan förlita sig på möjligheten att utföra en osignerad rätt skiftåtgärd.

Detaljerad design

Operatorer och skiljetecken

Avsnitt §6.4.6 justeras för att inkludera >>> operator – den osignerade höger skiftoperatören:

unsigned_right_shift
    : '>>>'
    ;

unsigned_right_shift_assignment
    : '>>>='
    ;

Inga tecken av något slag (inte ens blanksteg) tillåts mellan token i unsigned_right_shift och unsigned_right_shift_assignment produktioner. Dessa produktioner behandlas särskilt för att möjliggöra korrekt hantering av type_parameter_lists.

Skiftoperatorer

Avsnitt §12.11 justeras för att inkludera >>> operator – den osignerade högerskiftoperatorn:

Operatorerna <<, >> och >>> används för att utföra bitväxlingsåtgärder.

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

För en åtgärd av formuläret x << count eller x >> count eller x >>> counttillämpas binär operatoröverbelastningsmatchning (§12.4.5) för att välja en specifik operatorimplementering. Operanderna konverteras till parametertyperna för den valda operatorn och typen av resultat är operatorns returtyp.

De fördefinierade osignerade skiftoperatorerna har stöd för samma uppsättning signaturer som fördefinierade signerade skiftoperatorer stöder i dag i den aktuella implementeringen.

  • Skift höger:

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

    Operatorn >>> skiftar x rätt med ett antal bitar som beräknas enligt beskrivningen nedan.

    Lågordningsbitarna i x ignoreras, de återstående bitarna flyttas åt höger och de tomma bitpositionerna i hög ordning är inställda på noll.

För de fördefinierade operatorerna beräknas antalet bitar som ska flyttas enligt följande:

  • När typen av x är int eller uint, bestäms skiftantalet av de fem bitarna med lägre ordning i count. Med andra ord beräknas skiftantalet från count & 0x1F.
  • När typen av x är long eller ulongbestäms skiftantalet av de lägre sex bitarna av count. Med andra ord beräknas skiftantalet från count & 0x3F.

Om det resulterande skiftantalet är noll returnerar skiftoperatorerna helt enkelt värdet för x.

Skiftåtgärder orsakar aldrig spill och ger samma resultat i checked och unchecked kontexter.

Tilldelningsoperatorer

Avsnitt §12.21 justeras för att inkludera unsigned_right_shift_assignment enligt följande:

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

Integraltyper

Integraltyperna §8.3.6 avsnitt justeras för att inkludera information om >>> operatör. Den relevanta punktpunkten är följande:

  • För operatorerna binary <<, >> och >>> konverteras den vänstra operanden till typ T, där T är den första av int, uint, longoch ulong som helt kan representera alla möjliga värden för operand. Åtgärden utförs sedan med hjälp av precisionen av typen T, och typen av resultat är T.

Konstanta uttryck

Operatorn >>> läggs till i den uppsättning konstruktioner som tillåts i konstanta uttryck §12.23.

Operatörsöverlagring

Operatorn >>> läggs till i uppsättningen överlagrbara binära operatorer på §12.4.3.

Upplyfta operatorer

Operatorn >>> kommer att läggas till i uppsättningen av binära operatorer som tillåter en höjd form vid §12.4.8.

Operatorprioritet och associativitet

Avsnitt §12.4.2 justeras för att lägga till operatören >>> i kategorin "Skift" och operatören >>>= i kategorin "Tilldelning och lambda-uttryck".

Grammatiktydligheter

Den >>> operatorn är föremål för samma grammatik tvetydigheter som en vanlig operator, som beskrivs i >>.

Operatörer

Avsnittet §15.10 kommer att justeras för att inkludera operatören >>>.

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

Binära operatorer

Underskriften av en >>> operatör omfattas av samma regler som de på §15.10.3 för underskrift av en >> operatör.

Metadatanamn

Avsnitt "I.10.3.2 Binära operatorer" för ECMA-335 har redan reserverat namnet på en icke-tecknad högerskiftoperator – op_UnsignedRightShift.

Linq-uttrycksträd

Operatorn >>> stöds inte i Linq Expression Trees eftersom semantik för fördefinierade >>> operatorer på signerade typer inte kan representeras korrekt utan att konverteringar läggs till i en osignerad typ och tillbaka. Mer information finns i https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator.

Dynamisk bindning

Det verkar som om dynamisk bindning använder värden av System.Linq.Expressions.ExpressionType-enum för att kommunicera vilken typ av binär operator det rör sig om till körningstidsbindaren. Eftersom vi inte har någon medlem som specifikt representerar en högerförskjutningsoperator utan tecken, kommer dynamisk bindning för >>>-operatorn inte att stödjas och den statiska och dynamiska bindningen (§12.3) kommer att justeras för att återspegla detta.

Nackdelar

Alternativ

Linq-uttrycksträd

Operatorn >>> stöds i Linq Expressioin Trees.

  • För en användardefinierad operator skapas en BinaryExpression-nod som pekar på operatormetoden.
  • För fördefinierade operatorer
    • När den första operanden är en ansignerad typ skapas en BinaryExpression-nod.
    • När den första operanden är en signerad typ läggs en konvertering för den första operanden till en osignerad typ, en BinaryExpression-nod skapas och konvertering för resultatet tillbaka till den signerade typen läggs till.

Till exempel:

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

Resolution:

Avvisad, se https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator för ytterligare information.

Olösta frågor

Designa möten

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