简体   繁体   English

在泛型类中使用Activator.CreateInstance结合方法上的“ new”修饰符

[英]Using Activator.CreateInstance in generic class combined with “new” modifier on method

I have a class (DerivedClass) which inherits from BaseClass. 我有一个继承自BaseClass的类(DerivedClass)。 In DerivedClass I use the "new" modifier on a method (SayHello()) since I want to alter the signature - I want to add a return value. 在DerivedClass中,我在方法(SayHello())上使用“ new”修饰符,因为我想更改签名-我想添加一个返回值。
I also have a generic class. 我也有一个通用类。 The type supplied to the generic class should be of type "BaseClass" (in my case either BaseClass or DerivedClass). 提供给泛型类的类型应为“ BaseClass”类型(在我的情况下为BaseClass或DerivedClass)。

If I use Activator.CreateInstance<T>() to get a new instance of my generic type and then call my method then the method on BaseClass is always called. 如果我使用Activator.CreateInstance <T>()获取通用类型的新实例,然后调用我的方法,则始终会调用BaseClass上的方法。 Why doesn't the SayHello-method on DerivedClass get called when it is set as the generic type? 将DerivedClass上的SayHello方法设置为通用类型时,为什么不调用它?

I made a simple console application to illustrate: 我制作了一个简单的控制台应用程序来说明:

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();
        }
    }
}

Because you didn't override the method, you're shadowing it. 因为您没有覆盖该方法,所以将其隐藏起来。 If you made the method virtual, and override it instead, then you'd get the results you're expecting. 如果您将方法设为虚拟方法,而是对其进行覆盖,那么您将获得期望的结果。

The Run method of GenericClass doesn't know the runtime type of the object, it only knows that it's a type derived from BaseClass , and so it can only bind the implementation of the method in BaseClass at compile time. GenericClassRun方法不知道对象的运行时类型,它仅知道它是从BaseClass派生的类型,因此它只能在编译时绑定BaseClass中该方法的实现。 Since you haven't enabled virtual dispatch through making the method virtual , there's no way for it to know about the derived type's method. 由于尚未通过将方法设置为virtual来启用虚拟调度,因此无法知道派生类型的方法。

Because the combination of: 因为组合:

public class GenericClass<T> where T : BaseClass

And: 和:

new public int SayHello()

Tells the compiler, that at compile time, T would be of type BaseClass , and the method overload matching happens at compile time, not at runtime. 告诉编译器,在编译时T将为BaseClass类型,并且方法重载匹配发生在编译时,而不是在运行时。 Hence, the fact that your run-time type is different, doesn't actually come into play here as it was "ran over" using the new modifier, and not via overriding of a virtual method dispatch, as it would if the return type of both your method calls was the same ( void ). 因此,您的运行时类型不同的事实实际上并没有在这里发挥作用,因为它是使用new修饰符“运行”的,而不是通过覆盖虚拟方法分派(就像返回类型一样)您的两个方法调用都相同( void )。

You see it in the generated IL: 您会在生成的IL中看到它:

GenericClass`1.Run: 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.

相关问题 在使用Activator.CreateInstance创建的通用基类上调用方法 - Calling a method on a generic base class created with Activator.CreateInstance 使用Activator.CreateInstance进行通用类型转换 - Generic type casting using Activator.CreateInstance 是否可以使用Activator.CreateInstance()模拟方法? - Is it possible to mock a method with using of Activator.CreateInstance()? 具有通用存储库的Activator.CreateInstance - Activator.CreateInstance with a generic repository 无法使用通用方法类型 <T> 直接在Activator.CreateInstance中 - Unable to use generic method type <T> directly in Activator.CreateInstance 结合使用Activator.CreateInstance()和属性 - Using Activator.CreateInstance() with properties 是否可以使用Activator.CreateInstance()使用参数构造函数创建泛型工厂? - Is it possible to create a generic factory with constructor with parameters using Activator.CreateInstance()? 模拟静态方法Activator.CreateInstance以返回另一个类的模拟 - Mock static method Activator.CreateInstance to return a mock of another class 使用Activator.CreateInstance创建类的实例并将Interface注入构造函数 - Using Activator.CreateInstance to create instance of a class and inject Interface to constructor 无法使用Activator.CreateInstance创建COM类的实例 - Unable to Create the instance of COM class using Activator.CreateInstance
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM