Pesquisar

29 de fev de 2008

Chamar métodos static por tipo variável é ilegal - Parte I

Considere o seguinte:


    public class C { public static void M() { /*blablabla*/ } }

    public class D : C { public new static void M() { /*blablabla*/ } }

    public class E<T> where T : C { public static void N() { T.M(); } }


Isso é ilegal. Nós não podemos chamar um método static sob um tipo variável. A questão é, por quê? Nós sabemos que T deve ser um C, e C tem um método static M, então por que isto não é válido?

Espero que você concorde que uma das seguintes afirmações deve ser verdadeira:

1) Isto é inválido.
2) E<T>.N() chama C.M() não importa o que T é.
3) E<C>.N() chama C.M() mas E<D>.N() chama D.M().

Se nós pegarmos a opção 2, então isto é tão sem sentido quanto totalmente inútil. O usuário irá esperar que D.M() seja chamado se T for um D. Porque senão para que teriamos o trabalho de chamar T.M() em vez de C.M() se ele irá "sempre chamar C.M()"?

Se pegarmos a opção 3, então nós temos uma violação dos princípios de design do núcleo dos métodos static, o princípio que lhes deu o nome. Métodos estáticos são chamados “static” porque eles podem sempre determinar exatamente, em tempo de compilação, qual método será chamado. Ou seja, o método pode ser resolvido unicamente por análise estática do código.

Só sobra a opção 1.

Perguntas relacionadas são frequentemente abordadas, de várias formas. Muitas pessoas costumam perguntar porque C# não suporta métodos “virtual static”. Mas o que elas estão querendo dizer? Pois “virtual” e “static” são opostos! “virtual” significa“determinar o método a ser chamado baseado nas informações de tipo em tempo de execução”, e “static” significa“determinar o método a ser chamado unicamente baseado na análise estática em tempo de compilação”.

Na verdade o que as pessoas querem é um outro tipo de método, que não seja static, instanciado ou virtual. Nós poderiamos chegar à uma nova espécie de método que se comporta como a opção 3. Isto é, um método associado com o tipo (como um static), que não tem um argumento this "non-nullable" (diferente de um instanciado ou virtual), mas um onde o método chamado deve depender do tipo construído sobre o T (diferente de um static, o qual deve ser determinado em tempo de compilação).

Nenhum comentário: