![](/img/trans.png)
[英]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.