Isso é um inseto?
Sim.
Parabéns, você encontrou um bug na resolução de sobrecarga. O bug se reproduz em C # 4 e 5; não se reproduz na versão "Roslyn" do analisador semântico. Informei a equipe de teste do C # 5 e espero que possamos investigar e resolver isso antes do lançamento final. (Como sempre, sem promessas.)
Segue uma análise correta. Os candidatos são:
0: C(params string[]) in its normal form
1: C(params string[]) in its expanded form
2: C<string>(string)
3: C(string, object)
O candidato zero é obviamente inaplicável porque string
não é conversível para string[]
. Isso deixa três.
Dos três, devemos determinar o melhor método exclusivo. Fazemos isso fazendo comparações entre pares dos três candidatos restantes. Existem três desses pares. Todos eles têm listas de parâmetros idênticas, uma vez que retiramos os parâmetros opcionais omitidos, o que significa que temos que ir para a rodada de desempate avançada descrita na seção 7.5.3.2 da especificação.
Qual é melhor, 1 ou 2? O desempate relevante é que um método genérico é sempre pior do que um método não genérico. 2 é pior do que 1. Portanto, 2 não pode ser o vencedor.
Qual é melhor, 1 ou 3? O critério de desempate relevante é: um método aplicável apenas em sua forma expandida é sempre pior do que um método aplicável em sua forma normal. Portanto, 1 é pior do que 3. Portanto, 1 não pode ser o vencedor.
Qual é melhor, 2 ou 3? O desempate relevante é que um método genérico é sempre pior do que um método não genérico. 2 é pior do que 3. Portanto, 2 não pode ser o vencedor.
Para ser escolhido a partir de um conjunto de vários candidatos aplicáveis, um candidato deve estar (1) invicto, (2) vencer pelo menos um outro candidato e (3) ser o único candidato que possui as duas primeiras propriedades. O candidato três não é derrotado por nenhum outro candidato e vence pelo menos um outro candidato; é o único candidato com essa propriedade. Portanto, o candidato três é o único melhor candidato . Deve vencer.
Não apenas o compilador C # 4 está errando, como você observa corretamente que ele está relatando uma mensagem de erro bizarra. É um pouco surpreendente que o compilador esteja errando na análise de resolução de sobrecarga. Que ele esteja recebendo a mensagem de erro errada não é nada surpreendente; a heurística de erro de "método ambíguo" basicamente escolhe quaisquer dois métodos do conjunto de candidatos se um melhor método não puder ser determinado. Não é muito bom encontrar a ambigüidade "real", se é que ela existe.
Alguém pode razoavelmente perguntar por que isso acontece. É bastante complicado encontrar dois métodos que sejam "inequivocamente ambíguos" porque a relação de "melhor qualidade" é intransitiva . É possível encontrar situações em que o candidato 1 é melhor que 2, 2 é melhor que 3 e 3 é melhor que 1. Em tais situações, não podemos fazer melhor do que escolher dois deles como "os ambíguos".
Eu gostaria de melhorar essa heurística para Roslyn, mas é uma prioridade baixa.
(Exercício para o leitor: "Elabore um algoritmo de tempo linear para identificar o melhor membro único de um conjunto de n elementos onde a relação de melhor é intransitiva" foi uma das perguntas que me fizeram no dia em que entrevistei para esta equipe. Não é um algoritmo muito difícil; experimente.)
Um dos motivos pelos quais adiamos adicionar argumentos opcionais ao C # por tanto tempo foi o número de situações ambíguas complexas que ele introduz no algoritmo de resolução de sobrecarga; aparentemente, não acertamos.
Se desejar inserir um problema do Connect para rastreá-lo, fique à vontade. Se você apenas deseja que isso seja levado ao nosso conhecimento, considere feito. Vou continuar com testes no próximo ano.
Obrigado por trazer isso à minha atenção. Desculpas pelo erro.
'Overloaded.ComplexOverloadResolution(string)'
se refira ao<string>(string)
método; Acho que se refere ao(string, object)
método sem objeto fornecido.