[英]Calling method based on run-time type insead of compile-time type
在應用程序中,我需要.NET根據其運行時類型而不是其編譯時類型來調用方法。
簡化示例:
class A { }
class B : A { }
static void Main(string[] args)
{
A b = new B();
Print(b);
}
static void Print(A a)
{
Console.WriteLine("Called from A");
}
static void Print(B b)
{
Console.WriteLine("Called from B");
}
上面的代碼實際上將打印Called from A
,但我需要Called from B
。
這按預期工作:
static void Print(A a)
{
var b = a as B;
if (b != null)
return Print(b);
else
Console.WriteLine("Called from A");
}
但是出於可維護性的考慮,這是不可取的。
我相信這個問題與此類似: 為什么不基於其對象的運行時類型選擇此方法? ,但適用於.NET而不是Java。
如果您使用的是.NET 4或更高版本,則最簡單的方法是使用動態類型 :
dynamic b = new B();
Print(b);
幾乎所有使用dynamic
類型值的表達式都將被動態調用,“ mini-C#編譯器”將在執行時應用與編譯時相同的規則,但使用這些dynamic的實際執行時類型價值觀。 (盡管其類型在編譯時是靜態已知的表達式仍然會被視為具有這些類型-並不能使有關重載解析的所有內容變為動態。)
如果您不使用.NET 4,則難度會有所增加-您可以使用反射,也可以對選項進行硬編碼,但都不有趣。
您可以使用dynamic
類型:
A b = new B();
dynamic tmp = b;
Print(tmp); // Prints "Called from B"
但是,請注意,這樣做的缺點是,如果沒有匹配的方法,它將生成運行時異常,而不是編譯錯誤。
使用OOP的重寫。
范例:
class A {
public virtual void Print() {
Console.WriteLine("Called from A");
}
}
class B : A {
public override void Print() {
Console.WriteLine("Called from B");
}
}
並像這樣使用它:
A b = new B();
Print(b);
static void Print(A a)
{
a.Print(); //will run B's method
}
當您使用簡單的覆蓋概念時 ,它將運行運行時類型方法。
這不是多態的工作原理。 您應該考慮做類似以下的事情:
class A
{
virtual string GetString()
{
return "Called from A";
}
}
class B : A
{
override string GetString()
{
return "Called from B";
}
}
static void Main(string[] args)
{
A b = new B();
Print(b);
}
static void Print(A a)
{
Console.WriteLine(a.GetString());
}
嘗試這個:
class A
{
public virtual string Print()
{
return "Called from A";
}
}
class B : A
{
public override string Print()
{
return "Called from B";
}
}
並在其他地方進行測試
A b = new B();
MessageBox.Show(b.Print()); //called from B
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.