Pesquisar

17 de abr de 2008

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

Considere agora o método não-static e não-virtual:

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

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

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


Nesse contexto, uma das seguintes afirmações é 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.

Como temos discutido, para métodos static escolhemos a opção 1. Mas com métodos por instância, nós escolhemos a 2! A maioria das pessoas acharia que o método mais derivado(opção 3) seria chamado, mas não. Por quê? Porque temos que considerar que poderíamos ter: public static void N(C t) { t.M(); } o que nos faz esperar que o método menos derivado seja sempre chamado, desde que ele não seja virtual.

Por que não a opção 3? Novamente, tem a ver com análise estática. É que na realidade o que temos em ambos os casos, static e instanciados, C.M e D.M são métodos diferentes. O "new" solicita que eles sejam dois métodos diferentes que somente compartilham o mesmo nome. Você pode pensar em cada método como se ele ocupasse uma "vaga" no objeto, tanto em static como instanciado, nós definimos duas vagas, não uma. No caso do virtual e override então nós teríamos apenas uma vaga, e o conteúdo da vaga seria determinado em tempo de execução. Mas no caso não-virtual há duas vagas diferentes.

Quando o compilador gera o código generic, ele "calcula" todas as vagas em tempo de compilação. O jitter não as altera. Na verdade, o jitter não saberia como! O jitter não tem idéia que D.M tem qualquer coisa a ver com C.M. Novamente, eles são métodos totalmente diferentes que somente coincidentemente compartilham o mesmo nome. Eles têm vagas diferentes então são métodos diferentes.

Nenhum comentário: