O código a seguir tem um método estático Foo()
, chamando um método de instância Bar()
:
public sealed class Example
{
int count;
public static void Foo( dynamic x )
{
Bar(x);
}
void Bar( dynamic x )
{
count++;
}
}
Ele compila sem erros * mas gera uma exceção de fichário de tempo de execução no tempo de execução. Remover o parâmetro dinâmico para esses métodos causa um erro do compilador, como esperado.
Então, por que ter um parâmetro dinâmico permite que o código seja compilado? O ReSharper também não mostra isso como um erro.
Edição 1: * no Visual Studio 2008
Edição 2: adicionada sealed
porque é possível que uma subclasse contenha um Bar(...)
método estático . Mesmo a versão selada compila quando não é possível que qualquer método diferente do método de instância possa ser chamado em tempo de execução.
c#
visual-studio-2008
dynamic
compiler-errors
Mike Scott
fonte
fonte
dynamic
menos que seja realmente necessário.Respostas:
ATUALIZAÇÃO: a resposta abaixo foi escrita em 2012, antes da introdução do C # 7.3 (maio de 2018) . Em O que há de novo no C # 7.3 , a seção Candidatos de sobrecarga aprimorados , item 1, é explicado como as regras de resolução de sobrecarga foram alteradas para que as sobrecargas não estáticas sejam descartadas antecipadamente. Portanto, a resposta abaixo (e toda a questão) tem principalmente interesse apenas histórico agora!
(Pré C # 7.3 :)
Por alguma razão, a resolução de sobrecarga sempre encontra a melhor correspondência antes de verificar se há estática versus não estática. Tente este código com todos os tipos estáticos:
Isso não irá compilar porque a melhor sobrecarga é aquela que leva a
string
. Mas ei, esse é um método de instância, então o compilador reclama (em vez de aceitar a segunda melhor sobrecarga).Adição: Então, acho que a explicação do
dynamic
exemplo da Questão Original é que, para ser consistente, quando os tipos são dinâmicos, também encontramos primeiro a melhor sobrecarga (verificando apenas o número do parâmetro e os tipos de parâmetro etc., não estático x não -static), e só então verifique se há estática. Mas isso significa que a verificação estática deve esperar até o tempo de execução. Daí o comportamento observado.Adição tardia: Algumas informações básicas sobre por que eles escolheram fazer as coisas nessa ordem engraçada podem ser inferidas a partir desta postagem do blog de Eric Lippert .
fonte
dynamic
foi introduzido na linguagem, acho que os designers do C # disseram: "Não consideraremos (2) o tempo de compilação quando for umadynamic
expressão." Portanto, meu objetivo aqui é ter uma ideia de por que eles optaram por não verificar a existência de estática versus instância até o tempo de execução. Eu diria que essa verificação acontece no momento da vinculação .Foo tem um parâmetro "x" que é dinâmico, o que significa que Bar (x) é uma expressão dinâmica.
Seria perfeitamente possível que o Exemplo tivesse métodos como:
Nesse caso, o método correto seria resolvido, de modo que a declaração Bar (x) é perfeitamente válida. O fato de haver um método de instância Bar (x) é irrelevante e nem mesmo considerado: por definição , como Bar (x) é uma expressão dinâmica, adiamos a resolução para o tempo de execução.
fonte
A expressão "dinâmica" será vinculada durante o tempo de execução, portanto, se você definir um método estático com a assinatura correta ou um método de instância, o compilador não o verificará.
O método "certo" será determinado durante a execução. O compilador não pode saber se existe um método válido durante a execução.
A palavra-chave "dynamic" é definida para linguagens dinâmicas e de script, onde o Método pode ser definido a qualquer momento, mesmo durante a execução. Coisas doidas
Aqui, um exemplo que lida com ints, mas sem strings, por causa do método está na instância.
Você pode adicionar um método para tratar todas as chamadas "erradas", que não puderam ser tratadas
fonte