簡體   English   中英

在泛型類中使用Activator.CreateInstance結合方法上的“ new”修飾符

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

因為您沒有覆蓋該方法,所以將其隱藏起來。 如果您將方法設為虛擬方法,而是對其進行覆蓋,那么您將獲得期望的結果。

GenericClassRun方法不知道對象的運行時類型,它僅知道它是從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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM