Предположим, у меня есть два класса:
class a
{
public void sayGoodbye() { Console.WriteLine("Tschüss"); }
public virtual void sayHi() { Console.WriteLine("Servus"); }
}
class b : a
{
new public void sayGoodbye() { Console.WriteLine("Bye"); }
override public void sayHi() { Console.WriteLine("Hi"); }
}
Если я вызываю общий метод, который требует, чтобы тип «T» был производным от класса «a»:
void call<T>() where T : a
Затем внутри этого метода я вызываю методы для для экземпляра типа «T» вызов метода привязан к типу «a», как если бы экземпляр был приведен как «a»:
call<b>();
...
void call<T>() where T : a
{
T o = Activator.CreateInstance<T>();
o.sayHi(); // writes "Hi" (virtual method)
o.sayGoodbye(); // writes "Tschüss"
}
Используя отражение, я могу получить ожидаемые результаты:
call<b>();
...
void call<T>() where T : a
{
T o = Activator.CreateInstance<T>();
// Reflections works fine:
typeof(T).GetMethod("sayHi").Invoke(o, null); // writes "Hi"
typeof(T).GetMethod("sayGoodbye").Invoke(o, null); // writes "Bye"
}
Кроме того, используя интерфейс для класса 'a', я получаю ожидаемые результаты:
interface Ia
{
void sayGoodbye();
void sayHi();
}
...
class a : Ia // 'a' implements 'Ia'
...
call<b>();
...
void call<T>() where T : Ia
{
T o = Activator.CreateInstance<T>();
o.sayHi(); // writes "Hi"
o.sayGoodbye(); // writes "Bye"
}
Эквивалентный неуниверсальный код также отлично работает:
call();
...
void call()
{
b o = Activator.CreateInstance<b>();
o.sayHi(); // writes "Hi"
o.sayGoodbye(); // writes "Bye"
}
То же самое, если я изменю общее ограничение на 'b':
call<b>();
...
void call<T>() where T : b
{
T o = Activator.CreateInstance<T>();
o.sayHi(); // writes "Hi"
o.sayGoodbye(); // writes "Bye"
}
Кажется, что компилятор генерирует вызовы методов для базового класса, указанного в ограничении, поэтому я думаю, что понимаю, что происходит, но это не то, что я ожидал.Это действительно правильный результат?