Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Suporte à extensão
Observação
Este artigo é uma especificação de recurso. A especificação serve como o documento de design para o recurso. Ela inclui alterações de especificação propostas, juntamente com as informações necessárias durante o design e o desenvolvimento do recurso. Esses artigos são publicados até que as alterações de especificação propostas sejam finalizadas e incorporadas na especificação ECMA atual.
Pode haver algumas divergências entre a especificação do recurso e a implementação concluída. Essas diferenças são capturadas nas notas pertinentes da reunião de design de idioma (LDM).
Você pode saber mais sobre o processo de adoção de speclets de recursos no padrão de linguagem C# no artigo sobre as especificações de .
Problema do especialista: https://github.com/dotnet/csharplang/issues/3194
Resumo
Permitir que os loops foreach reconheçam um método de extensão GetEnumerator que satisfaça o padrão foreach e interajam com a expressão quando, de outra forma, resultaria em erro.
Motivação
Isso alinhará o foreach com a forma como outros recursos em C# são implementados, incluindo assíncrono e desconstrução baseada em padrão.
Projeto detalhado
A mudança de especificação é relativamente simples. Nós modificamos a seção The foreach statement§13.9.5 para este texto:
Primeiramente, o processamento em tempo de compilação de uma instrução foreach determina o tipo de coleção , o tipo de enumerador e o tipo de elemento da expressão. Esta determinação procede da seguinte forma:
Se o tipo
Xde expressão for um tipo de matriz, então há uma conversão de referência implícita deXpara a interfaceIEnumerable(já queSystem.Arrayimplementa essa interface). O tipo de coleção é a interfaceIEnumerable, o tipo de enumerador é a interfaceIEnumeratore o tipo de elemento é o tipo de elemento do tipo de matrizX.Se o tipo
Xde expressão fordynamic, haverá uma conversão implícita da expressão para a interfaceIEnumerable(§10.2.10). O tipo de coleção é a interfaceIEnumerablee o tipo de enumerador é a interfaceIEnumerator. Se o identificadorvarfor fornecido como local_variable_type, o tipo de elemento serádynamic; caso contrário, seráobject.Caso contrário, determine se o tipo
Xtem um métodoGetEnumeratorapropriado:
- Realize a pesquisa de membro no tipo
Xcom o identificadorGetEnumeratore sem argumentos de tipo. Se a pesquisa de membro não produzir uma correspondência ou produzir uma ambiguidade ou produzir uma correspondência que não seja um grupo de métodos, verifique se há uma interface enumerável, conforme descrito abaixo. É recomendável que um aviso seja emitido se a pesquisa de membros produzir algo além de um grupo de métodos ou nenhuma correspondência.- Execute a resolução de sobrecarga usando o grupo de métodos resultante e uma lista de argumentos vazia. Se a resolução de sobrecarga resultar em nenhum método aplicável, resultar em uma ambiguidade ou resultar em um único método melhor, mas esse método for estático ou não público, verifique se há uma interface enumerável conforme descrito abaixo. É recomendável que um aviso seja emitido se a resolução de sobrecarga produzir qualquer coisa, exceto um método de instância pública inequívoco ou se não houver métodos aplicáveis.
- Se o tipo de retorno
Edo métodoGetEnumeratornão for uma classe, struct ou tipo de interface, um erro será produzido e nenhuma etapa adicional será executada.- A consulta de membro é executada em
Ecom o identificadorCurrentsem argumentos de tipo. Se a pesquisa de membro não encontrar nenhuma correspondência, ou se o resultado for qualquer coisa exceto uma propriedade de instância pública que permita a leitura, um erro será produzido e nenhuma etapa adicional será executada.- A consulta de membro é executada em
Ecom o identificadorMoveNextsem argumentos de tipo. Se a pesquisa de membros não produzir nenhuma correspondência, o resultado for um erro ou o resultado for qualquer coisa, exceto um grupo de métodos, um erro será produzido e nenhuma outra etapa será executada.- A resolução de sobrecarga é executada no grupo de métodos com uma lista de argumentos vazia. Se a resolução de sobrecarga não resultar em métodos aplicáveis, resultar em uma ambiguidade ou resultar em um único melhor método, mas esse método for estático, não for público ou seu tipo de retorno não puder ser
bool, um erro é produzido e nenhuma outra etapa é seguida.- O tipo de coleção é
X, o tipo enumerador éEe o tipo de elemento é o tipo da propriedadeCurrent.Caso contrário, verifique se há uma interface enumerável:
- Se entre todos os tipos
Tipara os quais há uma conversão implícita deXparaIEnumerable<Ti>, existe um tipo únicoTde modo queTnão sejadynamice para todos os outrosTihá uma conversão implícita deIEnumerable<T>paraIEnumerable<Ti>, o tipo de coleção é a interfaceIEnumerable<T>, o tipo de enumerador é a interfaceIEnumerator<T>e o tipo de elemento éT.- Caso contrário, se houver mais de um tipo desse tipo
T, um erro é produzido e nenhuma outra etapa é executada.- Caso contrário, se houver uma conversão implícita de
Xpara a interfaceSystem.Collections.IEnumerable, o tipo de coleção é essa interface, o tipo de enumerador é a interfaceSystem.Collections.IEnumerator, e o tipo de elemento éobject.Caso contrário, determine se o tipo "X" tem um método de extensão
GetEnumeratorapropriado:
- Execute a pesquisa de método de extensão no tipo
Xcom o identificadorGetEnumerator. Se a pesquisa de membros não produzir uma correspondência, ou produzir uma ambiguidade, ou produzir uma correspondência que não seja um grupo de métodos, um erro será produzido e nenhuma outra etapa será executada. É recomendável que um aviso seja emitido se a pesquisa de membros produzir algo além de um grupo de métodos ou nenhuma correspondência.- Execute a resolução de sobrecarga usando o grupo de métodos resultante e um único argumento do tipo
X. Se a resolução de sobrecarga não produzir métodos aplicáveis, resultar em ambiguidade ou resultar em um único método melhor, mas esse método não for acessível, um erro será produzido e nenhuma etapa adicional será executada.
- Essa resolução permite que o primeiro argumento seja passado por referência se
Xfor um tipo de struct e o tipo ref forin.- Se o tipo de retorno
Edo métodoGetEnumeratornão for uma classe, struct ou tipo de interface, um erro será produzido e nenhuma etapa adicional será executada.- A consulta de membro é executada em
Ecom o identificadorCurrentsem argumentos de tipo. Se a pesquisa de membro não encontrar nenhuma correspondência, ou se o resultado for qualquer coisa exceto uma propriedade de instância pública que permita a leitura, um erro será produzido e nenhuma etapa adicional será executada.- A consulta de membro é executada em
Ecom o identificadorMoveNextsem argumentos de tipo. Se a pesquisa de membros não produzir nenhuma correspondência, o resultado for um erro ou o resultado for qualquer coisa, exceto um grupo de métodos, um erro será produzido e nenhuma outra etapa será executada.- A resolução de sobrecarga é executada no grupo de métodos com uma lista de argumentos vazia. Se a resolução de sobrecarga não resultar em métodos aplicáveis, resultar em uma ambiguidade ou resultar em um único melhor método, mas esse método for estático, não for público ou seu tipo de retorno não puder ser
bool, um erro é produzido e nenhuma outra etapa é seguida.- O tipo de coleção é
X, o tipo enumerador éEe o tipo de elemento é o tipo da propriedadeCurrent.Caso contrário, um erro será produzido e nenhuma outra etapa será executada.
Para await foreach, as regras são modificadas de forma semelhante. A única mudança necessária nessa especificação é remover a linha Extension methods do not contribute. da descrição, já que o restante da especificação é baseado nas regras acima, com nomes diferentes substituídos pelos métodos do padrão.
Desvantagens
Cada mudança acrescenta uma complexidade extra ao idioma, e isso potencialmente permite que coisas que não foram projetadas para serem foreach também sejam foreach, como Range.
Alternativas
Não fazer nada.
Perguntas não resolvidas
Nenhuma das opções no momento.
C# feature specifications