C# 在泛型类中结合使用Activator.CreateInstance;新";方法上的修改器
我有一个从基类继承的类(DerivedClass)。 在DerivedClass中,我对一个方法(SayHello())使用“new”修饰符,因为我想更改签名-我想添加一个返回值。C# 在泛型类中结合使用Activator.CreateInstance;新";方法上的修改器,c#,generics,inheritance,activator,C#,Generics,Inheritance,Activator,我有一个从基类继承的类(DerivedClass)。 在DerivedClass中,我对一个方法(SayHello())使用“new”修饰符,因为我想更改签名-我想添加一个返回值。 我还有一个泛型类。提供给泛型类的类型应该是“BaseClass”类型(在我的例子中是BaseClass或DerivedClass) 如果我使用Activator.CreateInstance()获取泛型类型的新实例,然后调用我的方法,那么基类上的方法总是被调用。当DerivedClass上的SayHello方法设置为
我还有一个泛型类。提供给泛型类的类型应该是“BaseClass”类型(在我的例子中是BaseClass或DerivedClass) 如果我使用Activator.CreateInstance()获取泛型类型的新实例,然后调用我的方法,那么基类上的方法总是被调用。当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();
}
}
}
namespace TestApp
{
使用制度;
班级计划
{
静态void Main(字符串[]参数)
{
var gc=新的GenericClass();
gc.Run();
}
}
公共类基类
{
公共空间
{
控制台。WriteLine(“你好!”);
}
}
公共类派生类:基类
{
新公共int SayHello()
{
WriteLine(“Hello returning int!”);
返回1;
}
}
公共类GenericClass,其中T:BaseClass
{
公开募捐
{
var bc=新的基类();
bc.SayHello();//你好!
var dc=新的DerivedClass();
dc.SayHello();//您好,返回int!
var dc2=Activator.CreateInstance();
dc2.SayHello();//你好!
Console.WriteLine(dc2.GetType());//TestApp.DerivedClass
Console.Read();
}
}
}
因为以下因素的组合:
public class GenericClass<T> where T : BaseClass
告诉编译器,在编译时,T
将是BaseClass
类型,方法重载匹配发生在编译时,而不是运行时。因此,您的运行时类型不同这一事实在这里实际上并不起作用,因为它是使用new
修饰符“运行”的,而不是通过重写虚拟方法分派来实现的,如果两个方法调用的返回类型相同(void
)
您可以在生成的IL中看到它:
GenericClass`1.运行:
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
因为:
public class GenericClass<T> where T : BaseClass
告诉编译器,在编译时,T
将是BaseClass
类型,方法重载匹配发生在编译时,而不是运行时。因此,您的运行时类型不同这一事实在这里实际上并不起作用,因为它是使用new
修饰符“运行”的,而不是通过重写虚拟方法分派来实现的,如果两个方法调用的返回类型相同(void
)
您可以在生成的IL中看到它:
GenericClass`1.运行:
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
因为:
public class GenericClass<T> where T : BaseClass
告诉编译器,在编译时,T
将是BaseClass
类型,方法重载匹配发生在编译时,而不是运行时。因此,您的运行时类型不同这一事实在这里实际上并不起作用,因为它是使用new
修饰符“运行”的,而不是通过重写虚拟方法分派来实现的,如果两个方法调用的返回类型相同(void
)
您可以在生成的IL中看到它:
GenericClass`1.运行:
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
因为:
public class GenericClass<T> where T : BaseClass
告诉编译器,在编译时,T
将是BaseClass
类型,方法重载匹配发生在编译时,而不是运行时。因此,您的运行时类型不同这一事实在这里实际上并不起作用,因为它是使用new
修饰符“运行”的,而不是通过重写虚拟方法分派来实现的,如果两个方法调用的返回类型相同(void
)
您可以在生成的IL中看到它:
GenericClass`1.运行:
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
因为您没有覆盖该方法,所以正在对其进行跟踪。如果您将该方法设置为虚拟,并替代它,那么您将得到预期的结果
GenericClass
的Run
方法不知道对象的运行时类型,它只知道它是从BaseClass
派生的类型,因此它只能在编译时在BaseClass
中绑定方法的实现。由于您没有通过使方法虚拟化来启用虚拟分派,因此它无法了解派生类型的方法。因为您没有重写该方法,所以正在对其进行跟踪。如果您将该方法设置为虚拟,并替代它,那么您将得到预期的结果
GenericClass
的Run
方法不知道对象的运行时类型,它只知道它是从BaseClass
派生的类型,因此它只能在编译时在BaseClass
中绑定方法的实现。由于您没有通过使方法虚拟化来启用虚拟分派,因此它无法了解派生类型的方法。因为您没有重写该方法,所以正在对其进行跟踪。如果您将该方法设置为虚拟,并替代它,那么您将得到预期的结果
GenericClass
的Run
方法不知道对象的运行时类型,它只知道它是从BaseClass
派生的类型,因此它只能在编译时在BaseClass
中绑定方法的实现。由于您没有通过使方法虚拟化来启用虚拟分派,因此它无法了解派生类型的方法。因为您没有重写该方法,所以正在对其进行跟踪。如果你把方法做得很好