C # e genéricos - por que o método na classe base é chamado em vez do novo método na classe derivada?
Se o argumento de tipo genérico (de uma classe de chamada ou método de chamada) for restrito comwhere T : Base
o novo método em T == Derived não é chamado, em vez disso, o método em Base é chamado.
Por que o tipo T é ignorado para a chamada de método, embora deva ser conhecido antes do tempo de execução?
Atualizar: MAS, quando a restrição está usando uma interface comowhere T : IBase
o método na classe Base é chamado (não o método na interface, que também é impossível).
Então isso significa que o sistema realmente é capaz de detectar os tipos que estão longe e ir além da restrição de tipos! Então, por que ele não vai além da restrição de tipo no caso de restrição tipada por classe?
Isso significa que o método na classe Base que implementa a interface tem uma palavra-chave de substituição implícita para o método?
Código de teste:
public interface IBase
{
void Method();
}
public class Base : IBase
{
public void Method()
{
}
}
public class Derived : Base
{
public int i = 0;
public new void Method()
{
i++;
}
}
public class Generic<T>
where T : Base
{
public void CallMethod(T obj)
{
obj.Method(); //calls Base.Method()
}
public void CallMethod2<T2>(T2 obj)
where T2 : T
{
obj.Method(); //calls Base.Method()
}
}
public class GenericWithInterfaceConstraint<T>
where T : IBase
{
public void CallMethod(T obj)
{
obj.Method(); //calls Base.Method()
}
public void CallMethod2<T2>(T2 obj)
where T2 : T
{
obj.Method(); //calls Base.Method()
}
}
public class NonGeneric
{
public void CallMethod(Derived obj)
{
obj.Method(); //calls Derived.Method()
}
public void CallMethod2<T>(T obj)
where T : Base
{
obj.Method(); //calls Base.Method()
}
public void CallMethod3<T>(T obj)
where T : IBase
{
obj.Method(); //calls Base.Method()
}
}
public class NewMethod
{
unsafe static void Main(string[] args)
{
Generic<Derived> genericObj = new Generic<Derived>();
GenericWithInterfaceConstraint<Derived> genericObj2 = new GenericWithInterfaceConstraint<Derived>();
NonGeneric nonGenericObj = new NonGeneric();
Derived obj = new Derived();
genericObj.CallMethod(obj); //calls Base.Method()
Console.WriteLine(obj.i);
genericObj.CallMethod2(obj); //calls Base.Method()
Console.WriteLine(obj.i);
genericObj2.CallMethod(obj); //calls Base.Method()
Console.WriteLine(obj.i);
genericObj2.CallMethod2(obj); //calls Base.Method()
Console.WriteLine(obj.i);
nonGenericObj.CallMethod(obj); //calls Derived.Method()
Console.WriteLine(obj.i);
nonGenericObj.CallMethod2(obj); //calls Base.Method()
Console.WriteLine(obj.i);
nonGenericObj.CallMethod3(obj); //calls Base.Method()
Console.WriteLine(obj.i);
obj.Method(); //calls Derived.Method()
Console.WriteLine(obj.i);
}
}
Saída:
0
0
0
0
1
1
1
2