Operatore di spostamento a destra senza segno
Nota
Questo articolo è una specifica di funzionalità. La specifica funge da documento di progettazione per la funzionalità. Include le modifiche specifiche proposte, insieme alle informazioni necessarie durante la progettazione e lo sviluppo della funzionalità. Questi articoli vengono pubblicati fino a quando le modifiche specifiche proposte non vengono completate e incorporate nella specifica ECMA corrente.
Potrebbero verificarsi alcune discrepanze tra la specifica di funzionalità e l'implementazione completata. Tali differenze vengono acquisite nelle note
Altre informazioni sul processo per l'adozione di speclet di funzionalità nello standard del linguaggio C# sono disponibili nell'articolo sulle specifiche di .
Problema del campione: https://github.com/dotnet/csharplang/issues/4682
Sommario
Un operatore di spostamento a destra senza segno sarà supportato da C# come operatore predefinito (per i tipi integrali primitivi) e come operatore definito dall'utente.
Motivazione
Quando si lavora con il valore integrale con segno, non è raro che sia necessario spostare i bit direttamente senza replicare il bit di ordine elevato in ogni turno. Anche se ciò può essere ottenuto per i tipi integrali primitivi con un operatore di spostamento regolare, è necessario eseguire un cast a un tipo senza segno prima dell'operazione di spostamento e un cast di ritorno al tipo originale dopo di essa. Nel contesto delle interfacce matematiche generiche che le librerie stanno pianificando di esporre, questo è potenzialmente più problematico poiché il tipo potrebbe non avere una controparte non segnata, definita o nota in anticipo dal codice matematico generico; tuttavia, un algoritmo potrebbe basarsi sulla capacità di effettuare un'operazione di spostamento a destra non segnata.
Progettazione dettagliata
Operatori e segni di punteggiatura
La sezione §6.4.6 verrà modificata per includere l'operatore >>>
- l'operatore di spostamento a destra senza segno:
unsigned_right_shift
: '>>>'
;
unsigned_right_shift_assignment
: '>>>='
;
Non sono consentiti caratteri di alcun tipo (nemmeno spazi vuoti) tra i token nelle unsigned_right_shift e unsigned_right_shift_assignment produzioni. Queste produzioni vengono trattate appositamente per consentire la corretta gestione delle type_parameter_list.
Operatori di spostamento
La sezione §12.11 verrà modificata per includere l'operatore >>>
, l'operatore di spostamento a destra senza segno:
Gli operatori <<
, >>
e >>>
vengono usati per eseguire operazioni di spostamento dei bit.
shift_expression
: additive_expression
| shift_expression '<<' additive_expression
| shift_expression right_shift additive_expression
| shift_expression unsigned_right_shift additive_expression
;
Per un'operazione di forma x << count
o x >> count
o x >>> count
, viene applicata la risoluzione dell'overload dell'operatore binario (§12.4.5) per selezionare un'implementazione specifica dell'operatore. Gli operandi vengono convertiti nei tipi di parametro dell'operatore selezionato e il tipo del risultato è il tipo restituito dell'operatore.
Gli operatori di spostamento senza segno predefiniti supporteranno lo stesso set di firme attualmente supportate dagli operatori di spostamento firmati predefiniti nell'implementazione corrente.
Sposta a destra:
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);
L'operatore
>>>
spostax
direttamente in base a un numero di bit calcolati come descritto di seguito.I bit di ordine basso di
x
vengono eliminati, i bit rimanenti vengono spostati a destra e le posizioni dei bit vuoti di ordine elevato vengono impostate su zero.
Per gli operatori predefiniti, il numero di bit da spostare viene calcolato come segue:
- Quando il tipo di
x
èint
ouint
, il conteggio degli spostamenti è determinato dai cinque bit di basso ordine dicount
. In altre parole, il conteggio dei turni viene calcolato dacount & 0x1F
. - Quando il tipo di
x
èlong
oulong
, il conteggio dei bit di spostamento è determinato dai sei bit di ordine inferiore dicount
. In altre parole, il conteggio dei turni viene calcolato dacount & 0x3F
.
Se il conteggio dei turni risultante è zero, gli operatori di spostamento restituiscono semplicemente il valore di x
.
Le operazioni di spostamento non causano mai overflow e producono gli stessi risultati nei contesti checked
e unchecked
.
Operatori di assegnazione
La sezione §12.21 verrà modificata in modo da includere unsigned_right_shift_assignment come indicato di seguito:
assignment_operator
: '='
| '+='
| '-='
| '*='
| '/='
| '%='
| '&='
| '|='
| '^='
| '<<='
| right_shift_assignment
| unsigned_right_shift_assignment
;
Tipi integrali
I tipi integrali sezione 8.3.6 verranno modificati in modo da includere informazioni sull'operatore >>>
. Il punto elenco pertinente è il seguente:
- Per gli operatori binari
<<
,>>
e>>>
, l'operando sinistro viene convertito nel tipoT
, doveT
è il primo diint
,uint
,long
eulong
che può rappresentare completamente tutti i valori possibili dell'operando. L'operazione viene quindi eseguita utilizzando la precisione del tipoT
e il tipo del risultato èT
.
Espressioni costanti
L'operatore >>>
verrà aggiunto al set di costrutti consentiti nelle espressioni costanti in §12.23.
Sovraccarico degli operatori
L'operatore >>>
verrà aggiunto all'insieme di operatori binari sovraccaricabili a §12.4.3.
Operatori elevati
L'operatore >>>
verrà aggiunto all'insieme di operatori binari che consente una forma elevata in §12.4.8.
Precedenza e associatività degli operatori
La sezione §12.4.2 verrà modificata per aggiungere l'operatore >>>
alla categoria "Shift" e l'operatore >>>=
alla categoria "Assegnazione ed espressione lambda".
Ambiguità grammaticali
L'operatore >>>
è soggetto alle stesse ambiguità grammaticali descritte in §6.2.5 come operatore >>
regolare.
Operatori
La sezione §15.10 verrà modificata per includere l'operatore >>>
.
overloadable_binary_operator
: '+' | '-' | '*' | '/' | '%' | '&' | '|' | '^' | '<<'
| right_shift | unsigned_right_shift | '==' | '!=' | '>' | '<' | '>=' | '<='
;
Operatori binari
La firma di un operatore >>>
è soggetta alle stesse regole riportate nella sezione §15.10.3 per la firma di un operatore >>
.
Il nome del metadato
La sezione "I.10.3.2 Operatori binari" di ECMA-335 ha già riservato il nome per un operatore di spostamento a destra senza segno - op_UnsignedRightShift.
Alberi delle espressioni LINQ
L'operatore >>>
non sarà supportato in Alberi delle espressioni Linq perché la semantica degli operatori di >>>
predefiniti sui tipi firmati non può essere rappresentata con precisione senza aggiungere conversioni a un tipo senza segno e indietro. Per altre informazioni, vedere https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator.
Collegamento dinamico
L'associazione dinamica usa i valori dell'enumerazione System.Linq.Expressions.ExpressionType per comunicare il tipo di operatore binario al gestore di runtime. Poiché non abbiamo un membro che rappresenta specificamente un operatore di spostamento a destra senza segno, l'associazione dinamica per l'operatore >>>
non sarà supportata e la sezione sull'associazione statica e dinamica (§12.3) verrà modificata per riflettere questo aspetto.
Svantaggi
Alternative
Alberi delle espressioni LINQ
L'operatore >>>
sarà supportato in Linq Expression Trees.
- Per un operatore definito dall'utente, verrà creato un nodo BinaryExpression che punta al metodo dell'operatore.
- Per gli operatori predefiniti
- quando il primo operando è un tipo firmato, verrà creato un nodo BinaryExpression.
- quando il primo operando è un tipo con segno, verrà aggiunta una conversione per il primo operando in un tipo senza segno, verrà creato un nodo BinaryExpression e verrà aggiunta la conversione del risultato a un tipo con segno.
Per esempio:
Expression<System.Func<int, int, int>> z = (x, y) => x >>> y; // (x, y) => Convert((Convert(x, UInt32) >> y), Int32)
Resolution:
Rifiutata, vedere https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator per altre informazioni.
Domande non risolte
Riunioni di design
https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md
C# feature specifications