Em C#, quando um objeto é declarado como dynamic, o compilador nos permite invocar qualquer método a partir desse objeto, sem checar em tempo de compilação se este método existe ou não. Esse recurso é conhecido como Dynamic Method Binding e apenas em tempo de execução o Framework irá informar, através de uma exceção, que o método invocado não existe.
Exemplo:
dynamic objetoDesconhecido = ObtemObjetoDesconhecidoDeAlgumLugar(); objetoDesconhecido.MetodoQueNaoExiste(); // Compila mas não executaNão quero discutir aqui o propósito dessa inclusão à linguagem, quero apenas apresentar uma construção bastante interessante permitida com o uso desse recurso.
Imagine escrever um conjunto de métodos privados sobrecarregados, cada um tratando um tipo específico de entrada e delegar a um único método público a função de decidir qual dos métodos privados deve ser executado.
O exemplo abaixo faz isso:
public class Taxonomy { public string GenusFor(IAnimal animal) { if (animal is Lion) return GenusFor((Lion)animal); if (animal is Zebra) return GenusFor((Zebra)animal); if (animal is Elephant) return GenusFor((Elephant)animal); return null; } private string GenusFor(Lion lion) { return "Lion"; } private string GenusFor(Zebra zebra) { return "Zebra"; } private string GenusFor(Elephant elephant) { return "Elephant"; } }O código acima pode parecer desnecessário se considerarmos que o genero do animal poderia ser uma simples propriedade da interface IAnimal, no entanto serve bem para ilustrar a ideia.
Veja como esse mesmo código ficaria se utilizássemos tipagem dinâmica para deixar que o .NET Framework decida em tempo de execução qual a versão do método GenusFor deve ser executada:
public class Taxonomy { public string GenusFor(IAnimal animal) { return ((dynamic)this).GenusFor((dynamic)animal); } private string GenusFor(Lion lion) { return "Lion"; } private string GenusFor(Zebra zebra) { return "Zebra"; } private string GenusFor(Elephant elephant) { return "Elephant"; } }
Usando ((dynamic)this), informamos ao compilador que queremos que o this seja tratado como um tipo dinâmico, assim a existência de um método GenusFor com os parâmetros informados não será verificada em tempo de compilação.
Em tempo de execução, o CLR irá procurar por um método chamado GenusFor no objeto this e encontrará 4 sobrecargas, 1 pública e 3 privadas. Nesses casos, o comportamento do CLR é utilizar o método cujos tipos dos parâmetros esperados sejam o mais próximos possíveis dos parâmetros passados. Isso faz com que o método correto seja invocado, conforme o tipo de IAnimal recebido como parâmetro.
Interessante, não? No entanto lembre-se que recursos poderosos como esse devem ser usados com muita cautela. Brinque um pouco com o código disponível no GitHub e veja o impacto positivo e negativo que esse tipo de abordagem pode trazer.
Confira também o uso desse recurso em um dos exemplos citados no livro Implementing Domain-Driven Design, de Vaugh Vernon.
Abraços.
Nenhum comentário:
Postar um comentário