Compartilhar via


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 >>> desloca x 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 ou uint, a contagem de turnos é dada pelos cinco bits de ordem baixa de count. Em outras palavras, a contagem de turnos é calculada a partir de count & 0x1F.
  • Quando o tipo de x é long ou ulong, a contagem de turnos é dada pela ordem baixa de seis bits de count. Em outras palavras, a contagem de turnos é calculada a partir de count & 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 tipo T, onde T é o primeiro de int, uint, longe ulong que podem representar totalmente todos os valores possíveis do operando. A operação é então realizada usando a precisão do tipo T, 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