[英]Calling a method on a generic base class created with Activator.CreateInstance
[英]Using Activator.CreateInstance in generic class combined with “new” modifier on method
我有一个继承自BaseClass的类(DerivedClass)。 在DerivedClass中,我在方法(SayHello())上使用“ new”修饰符,因为我想更改签名-我想添加一个返回值。
我也有一个通用类。 提供给泛型类的类型应为“ BaseClass”类型(在我的情况下为BaseClass或DerivedClass)。
如果我使用Activator.CreateInstance <T>()获取通用类型的新实例,然后调用我的方法,则始终会调用BaseClass上的方法。 将DerivedClass上的SayHello方法设置为通用类型时,为什么不调用它?
我制作了一个简单的控制台应用程序来说明:
namespace TestApp
{
using System;
class Program
{
static void Main(string[] args)
{
var gc = new GenericClass<DerivedClass>();
gc.Run();
}
}
public class BaseClass
{
public void SayHello()
{
Console.WriteLine("Hello!");
}
}
public class DerivedClass : BaseClass
{
new public int SayHello()
{
Console.WriteLine("Hello returning int!");
return 1;
}
}
public class GenericClass<T> where T : BaseClass
{
public void Run()
{
var bc = new BaseClass();
bc.SayHello(); // Hello!
var dc = new DerivedClass();
dc.SayHello(); // Hello returning int!
var dc2 = Activator.CreateInstance<T>();
dc2.SayHello(); // Hello!
Console.WriteLine(dc2.GetType()); // TestApp.DerivedClass
Console.Read();
}
}
}
因为您没有覆盖该方法,所以将其隐藏起来。 如果您将方法设为虚拟方法,而是对其进行覆盖,那么您将获得期望的结果。
GenericClass
的Run
方法不知道对象的运行时类型,它仅知道它是从BaseClass
派生的类型,因此它只能在编译时绑定BaseClass
中该方法的实现。 由于尚未通过将方法设置为virtual
来启用虚拟调度,因此无法知道派生类型的方法。
因为组合:
public class GenericClass<T> where T : BaseClass
和:
new public int SayHello()
告诉编译器,在编译时T
将为BaseClass
类型,并且方法重载匹配发生在编译时,而不是在运行时。 因此,您的运行时类型不同的事实实际上并没有在这里发挥作用,因为它是使用new
修饰符“运行”的,而不是通过覆盖虚拟方法分派(就像返回类型一样)您的两个方法调用都相同( void
)。
您会在生成的IL中看到它:
GenericClass`1.Run:
IL_001B: call 01 00 00 2B
IL_0020: stloc.2 // dc2
IL_0021: ldloca.s 02 // dc2
IL_0023: constrained. 02 00 00 1B
IL_0029: callvirt UserQuery+BaseClass.SayHello
您可以使用动态关键字:
dynamic dc2 = Activator.CreateInstance<T>();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.