C# 在泛型类中结合使用Activator.CreateInstance;新";方法上的修改器

C# 在泛型类中结合使用Activator.CreateInstance;新";方法上的修改器,c#,generics,inheritance,activator,C#,Generics,Inheritance,Activator,我有一个从基类继承的类(DerivedClass)。 在DerivedClass中,我对一个方法(SayHello())使用“new”修饰符,因为我想更改签名-我想添加一个返回值。 我还有一个泛型类。提供给泛型类的类型应该是“BaseClass”类型(在我的例子中是BaseClass或DerivedClass) 如果我使用Activator.CreateInstance()获取泛型类型的新实例,然后调用我的方法,那么基类上的方法总是被调用。当DerivedClass上的SayHello方法设置为

我有一个从基类继承的类(DerivedClass)。 在DerivedClass中,我对一个方法(SayHello())使用“new”修饰符,因为我想更改签名-我想添加一个返回值。
我还有一个泛型类。提供给泛型类的类型应该是“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
中绑定方法的实现。由于您没有通过使方法
虚拟化来启用虚拟分派,因此它无法了解派生类型的方法。

因为您没有重写该方法,所以正在对其进行跟踪。如果你把方法做得很好