Partilhar via


Melhorias no tipo natural de grupo de métodos

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 .

Questão campeã: https://github.com/dotnet/csharplang/issues/7429

Resumo

Esta proposta refina a determinação do tipo natural de um grupo de métodos de algumas maneiras:

  1. Considere métodos candidatos escopo por escopo (métodos de instância primeiro, depois cada escopo subsequente de métodos de extensão)
  2. Remova candidatos que não têm hipótese de sucesso, para que não interfiram na determinação de uma assinatura exclusiva.
    • Prune métodos de instância genérica quando nenhum argumento de tipo é fornecido (var x = M;)
    • Prune métodos de extensão genéricos baseados em ser capaz de reduzir a extensão e em restrições

Contexto sobre o tipo natural do grupo de métodos

Em C# 10, os grupos de métodos ganharam um tipo natural fraco.
Esse tipo é um "tipo fraco" na medida em que só entra em jogo quando o grupo de métodos não é tipado como alvo (ou seja, não desempenha nenhum papel em System.Action a = MethodGroup;).
Esse tipo natural fraco permite cenários como var x = MethodGroup;.

Para referência: https://github.com/dotnet/csharplang/blob/main/proposals/csharp-10.0/lambda-improvements.md#natural-function-type

Um grupo de métodos tem um tipo natural se todos os métodos candidatos no grupo de métodos tiverem uma assinatura comum. (Se o grupo de métodos puder incluir métodos de extensão, os candidatos incluem o tipo que contém e todos os escopos do método de extensão.)

Na prática, isto significa que:

  1. Construa o conjunto de todos os métodos candidatos:
  • métodos no tipo relevante estão no conjunto se eles são estáticos e o recetor é um tipo, ou se eles são não-estáticos e o recetor é um valor
  • Os métodos de extensão (em todas as esferas) que podem ser reduzidos estão incluídos no conjunto.
  1. Se as assinaturas de todos os candidatos não corresponderem, então o grupo de métodos não tem um tipo natural
  2. Se a aridade da assinatura resultante não corresponder ao número de argumentos de tipo fornecidos, o grupo de métodos não terá um tipo natural
  3. Caso contrário, a assinatura resultante é usada como o tipo natural

Proposta

O princípio é ir escopo a escopo e podar candidatos que sabemos que não podem ter sucesso o mais cedo possível (mesmo princípio usado na resolução de sobrecarga).

  1. Para cada escopo, construímos o conjunto de todos os métodos candidatos:
  • Para o escopo inicial, os métodos no tipo relevante cuja aridade corresponda aos argumentos de tipo fornecidos e que satisfaçam as restrições com os argumentos de tipo fornecidos estão incluídos no conjunto se forem estáticos e o receptor for um tipo, ou se forem não-estáticos e o receptor for um valor.
  • Para escopos subsequentes, os métodos de extensão nesse escopo que podem ser substituídos pelos argumentos de tipo fornecidos e reduzidos com o valor do receptor, enquanto satisfazem as restrições, estão no conjunto.
  1. Se não tivermos candidatos no âmbito dado, avance para o âmbito seguinte.
  2. Se as assinaturas de todos os candidatos não corresponderem, então o grupo de métodos não tem um tipo natural
  3. Caso contrário, a assinatura resultante é usada como o tipo natural
  4. Se os escopos estiverem esgotados, o grupo de métodos não terá um tipo natural

Relaciona-se com a proposta por âmbito: https://github.com/dotnet/csharplang/issues/7364 Refere-se à proposta para melhor lidar com os métodos genéricos de extensão: https://github.com/dotnet/roslyn/issues/69222