O código de amostra testado no comportamento do .NET 2/3/4 / 4.5 / 4.6.1 e .Net Core 2.1 é o mesmo para todos, por que isso é tratado assim?
Claramente, a chamada para PrintIt<T>
está criando o tipo correto Bar
mas nunca realmente chama o método correto.
interface PrintMe
{
void Print();
}
class Foo : PrintMe
{
public void Print()
{
Console.WriteLine("Foo!");
}
}
class Bar : Foo
{
public new void Print()
{
Console.WriteLine("Bar!");
}
}
class Program
{
static void Main(string[] args)
{
PrintIt<Foo>();
PrintIt<Bar>();
var foo = new Foo();
var bar = new Bar();
foo.Print();
bar.Print();
Console.ReadKey();
}
static void PrintIt<T>() where T : PrintMe, new()
{
new T().Print();
}
}
Foo!
Foo!
Foo!
Bar!
Foo!
Bar!
Foo!
Bar!
Quando você 'novo' Print (), esse método não faz parte da interface do PrintMe.
Você obterá o mesmo resultado com
((PrintMe)new Bar()).Print();
Sem genéricos.
Não é uma questão do que o CLR faz, é uma questão do que a linguagem faz. A especificação C # diz :
Uma classe herda todas as implementações de interface fornecidas por suas classes básicas.
Sem explicitamente re-implementação de uma interface, uma classe de derivados não podem de qualquer forma alterar os mapeamentos de interface que herda das classes de base.
A especificação fornece um exemplo quase idêntico ao anterior.
Isso também significa que, para fazer com que ele se comporte da maneira que você deseja, é necessário reimplementar a interface:
c#
class Bar : Foo, PrintMe
{
public new void Print()
{
Console.WriteLine("Bar!");
}
}
@svick Obrigado pela resposta
Comentários muito úteis
Quando você 'novo' Print (), esse método não faz parte da interface do PrintMe.
Você obterá o mesmo resultado com
Sem genéricos.