Operador de turno direito não assinado
Observação
Este artigo é uma especificação de recurso. A especificação serve como o documento de design para o recurso. Ele inclui mudanças de especificação propostas, juntamente com as informações necessárias durante o design e desenvolvimento do recurso. Estes artigos são publicados até que as alterações de especificações propostas sejam finalizadas e incorporadas na especificação ECMA atual.
Pode haver algumas discrepâncias entre a especificação do recurso e a implementação concluída. Essas diferenças são capturadas nas notas pertinentes da Language Design Meeting (LDM).
Você pode saber mais sobre o processo de adoção de especificações de recursos no padrão de linguagem C# no artigo sobre as especificações .
Resumo
Um operador de deslocamento à direita sem sinal será suportado em C# como um operador embutido (para tipos integrais primitivos) e como um operador definido pelo utilizador.
Motivação
Ao trabalhar com valor integral assinado, não é incomum que você precise deslocar bits para a direita sem replicar o bit de ordem alta em cada turno. Embora isso possa ser alcançado para tipos integrais primitivos com um operador de deslocamento regular, é necessária uma conversão para um tipo não assinado antes da operação de deslocamento e um cast de volta depois. Dentro do contexto das interfaces matemáticas genéricas que as bibliotecas estão planejando expor, isso é potencialmente mais problemático, pois o tipo pode não ter necessariamente uma contraparte não assinada definida ou conhecida antecipadamente pelo código matemático genérico, mas um algoritmo pode depender da capacidade de executar uma operação de deslocamento à direita não assinada.
Projeto detalhado
Operadores e pontuadores
Seção §6.4.6 será ajustada para incluir o operador >>>
- o operador de deslocamento à direita não assinado:
unsigned_right_shift
: '>>>'
;
unsigned_right_shift_assignment
: '>>>='
;
Nenhum personagem de qualquer tipo (nem mesmo espaço em branco) é permitido entre os tokens em unsigned_right_shift e unsigned_right_shift_assignment produções. Estas produções são tratadas especialmente de forma a permitir o correto manuseamento de type_parameter_lists.
Operadores de turnos
A Seção §12.11 será ajustada para incluir >>>
operador - o operador de turno direito não assinado:
Os operadores <<
, >>
e >>>
são usados para executar operações de deslocamento de bits.
shift_expression
: additive_expression
| shift_expression '<<' additive_expression
| shift_expression right_shift additive_expression
| shift_expression unsigned_right_shift additive_expression
;
Para uma operação da forma x << count
ou x >> count
ou x >>> count
, a resolução de sobrecarga do operador binário (§12.4.5) é aplicada para selecionar uma implementação de operador específico. Os operandos são convertidos para os tipos de parâmetros do operador selecionado, e o tipo do resultado é o tipo de retorno do operador.
Os operadores de turno não assinado predefinidos suportarão o mesmo conjunto de assinaturas que os operadores de turno assinado predefinidos suportam hoje na implementação atual.
Vire para a direita:
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);
O operador
>>>
deslocax
para a direita por um número de bits calculados conforme descrito abaixo.Os bits de ordem baixa de
x
são descartados, os bits restantes são deslocados para a direita e as posições de bits vazios de ordem alta são definidas como zero.
Para os operadores predefinidos, o número de bits a deslocar é calculado da seguinte forma:
- Quando o tipo de
x
éint
ouuint
, a contagem de turnos é dada pelos cinco bits de ordem baixa decount
. Em outras palavras, a contagem de turnos é calculada a partir decount & 0x1F
. - Quando o tipo de
x
élong
ouulong
, a contagem de turnos é dada pela ordem baixa de seis bits decount
. Em outras palavras, a contagem de turnos é calculada a partir decount & 0x3F
.
Se a contagem de turnos resultante for zero, os operadores de turno simplesmente retornarão o valor de x
.
As operações de deslocamento nunca causam transbordamentos e produzem os mesmos resultados nos contextos checked
e unchecked
.
Operadores de atribuição
A Seção §12.21 será ajustada para incluir unsigned_right_shift_assignment da seguinte forma:
assignment_operator
: '='
| '+='
| '-='
| '*='
| '/='
| '%='
| '&='
| '|='
| '^='
| '<<='
| right_shift_assignment
| unsigned_right_shift_assignment
;
Tipos integrais
Os tipos integrais na seção §8.3.6 serão ajustados para incluir informações sobre o operador >>>
. O ponto relevante é o seguinte:
- Para os operadores binários
<<
,>>
e>>>
, o operando esquerdo é convertido em tipoT
, ondeT
é o primeiro deint
,uint
,long
eulong
que podem representar totalmente todos os valores possíveis do operando. A operação é então realizada usando a precisão do tipoT
, e o tipo do resultado éT
.
Expressões constantes
O operador >>>
será adicionado ao conjunto de construções permitidas em expressões constantes em §12.23.
Sobrecarga do operador
O operador >>>
será adicionado ao conjunto de operadores binários sobrecarregáveis em §12.4.3.
Operadores de elevadores
O operador >>>
será adicionado ao conjunto de operadores binários que permitem uma forma liftada em §12.4.8.
Precedência dos operadores e associatividade
A seção §12.4.2 será ajustada para adicionar o operador >>>
à categoria "Shift" e o operador >>>=
à categoria "Atribuição e expressão lambda".
Ambiguidades gramaticais
O operador >>>
está sujeito às mesmas ambiguidades gramaticais descritas no §6.2.5 que um operador >>
regular.
Operadores
A seção §15.10 será ajustada para incluir o operador >>>
.
overloadable_binary_operator
: '+' | '-' | '*' | '/' | '%' | '&' | '|' | '^' | '<<'
| right_shift | unsigned_right_shift | '==' | '!=' | '>' | '<' | '>=' | '<='
;
Operadores binários
A assinatura de um operador de >>>
está sujeita às mesmas regras que §15.10.3 para a assinatura de um operador de >>
.
Nome dos metadados
A seção "I.10.3.2 Operadores binários" do ECMA-335 já reservou o nome para um operador de deslocamento à direita não assinado - op_UnsignedRightShift.
Árvores de Expressão Linq
O operador >>>
não será suportado em Árvores de Expressão Linq porque a semântica dos operadores >>>
predefinidos em tipos assinados não pode ser representada com precisão sem a adição de conversões para um tipo não assinado e de volta. Consulte https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator para obter mais informações.
Vinculação dinâmica
Parece que a vinculação dinâmica usa os valores do enum System.Linq.Expressions.ExpressionType para indicar o tipo de operador binário ao vinculador de tempo de execução. Como não temos um membro que represente especificamente um operador de deslocamento à direita não assinado, a associação dinâmica para o operador >>>
não será suportada, e a seção de associação estática e dinâmica (, §12.3,) será ajustada para refletir isso.
Desvantagens
Alternativas
Árvores de Expressão Linq
O operador >>>
será apoiado em Linq Expressioin Trees.
- Para um operador personalizado pelo usuário, um nó de Expressão Binária apontando para o método do operador será criado.
- Para operadores predefinidos
- quando o primeiro operando for um tipo assinado, um nó BinaryExpression será criado.
- quando o primeiro operando for um tipo assinado, será realizada uma conversão do primeiro operando para um tipo não assinado, um nó BinaryExpression será criado e será feita a conversão do resultado de volta para o tipo assinado.
Por exemplo:
Expression<System.Func<int, int, int>> z = (x, y) => x >>> y; // (x, y) => Convert((Convert(x, UInt32) >> y), Int32)
Resolution:
Rejeitado, consulte https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator para obter mais informações.
Questões por resolver
Reuniões de design
https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md
C# feature specifications