![](/img/trans.png)
[英]Should overloaded methods with value types be consolidated into a generic method?
[英]Use of generic types in overloaded methods
我有一個通用的方法:
public bool DoSomething<T>(T item) where T: IBase
{
return DoSomethingSpecific(item);
}
public bool DoSomethingSpecific(IBase item)
{
return true;
}
public bool DoSomethingSpecific(IAdvanced item)
{
return false;
}
請注意,IAdvanced接口從IBase接口派生/繼承。
我發現如果我調用DoSomething,其中項目的類型為IAdvanced,它仍然總是返回false。 我不明白這一點。 我知道,因為IAdvanced是一個類型IBase(因為它是這個接口的子代),它可能會導致DoSomethingSpecific方法的2個重載類型之間的混淆。 但是,正如我對有限的C#知識所理解的那樣,應該在這里選擇IAdvanced方法。 這是我如何得出這個結論的一個例子:
public class Advanced: IAdvanced
{
public void CallMethod()
{
DoSomething(this);
}
}
這導致了真正的價值。
但是,如果我這樣做:
public class Advanced: IAdvanced
{
public void CallMethod()
{
DoSomethingSpecific(this);
}
}
它返回false,這是我所期望的。
我不得不說我之前從未使用過仿制葯。 我曾試過,但總是陷入這樣的情況,然后完全沒有看到使用泛型的意義(除了樹和鏈表之類的數據結構)。
這次我決定來這里尋求一些建議。 我試圖做的是否有明顯的問題? 嘗試做我在這里忙的事情可能沒有意義嗎?
我無法重現這一點,這意味着其他可能正在發生。 我懷疑你實際上是想說它總是回歸真實 。 這就是我在這里看到的:
using System;
public interface IBase {}
public interface IAdvanced : IBase {}
public class Base : IBase {}
public class Advanced : IAdvanced {}
class Test
{
public static bool DoSomething<T>(T item) where T: IBase
{
return DoSomethingSpecific(item);
}
public static bool DoSomethingSpecific(IBase item)
{
return true;
}
public static bool DoSomethingSpecific(IAdvanced item)
{
return false;
}
static void Main()
{
Console.WriteLine(DoSomething(new Base())); // True
Console.WriteLine(DoSomething(new Advanced())); // True
}
}
現在你也寫:
我知道,因為IAdvanced是一個類型IBase(因為它是這個接口的子代),它可能會導致DoSomethingSpecific方法的2個重載類型之間的混淆。 但是,正如我對有限的C#知識所理解的那樣,應該在這里選擇IAdvanced方法。
當然,你應該期望返回false
- 而我希望返回true
。
你看, DoSomething<T>
的重載決議是在編譯該方法時確定的。 這種選擇只做一次 - 對於每個不同的T
都不是一次。 因此,如果您查看已編譯的IL中的DoSomething<T>
,您將只看到對DoSomethingSpecific(IBase)
的調用,而不是 DoSomethingSpecific(IAdvanced)
。 這里沒有多態性。
至於如何“修復”這個 - 你需要更詳細地解釋你真正想要實現的目標。 特別是,如果你有這個代碼,你會想要發生什么:
IBase x = new AdvancedImplementation();
DoSomething(x);
這里的T
將是IBase
,但該值將指IAdvanced
的實現。 如果你想在這種情況下執行DoSomethingSpecific(IAdvanced)
,並且你正在使用C#4,那么你可以使用動態類型:
public static bool DoSomething(IBase item)
{
dynamic dynamicItem = item;
// Dispatch dynamically based on execution-time type
return DoSomethingSpecific(dynamicItem);
}
請注意該方法不再需要通用 - 它不會帶來任何好處。
另一方面,如果您想要決定僅基於T
調用哪個,則需要使用類似ivowiblo的解決方案。
就個人而言,我會盡量避免這兩種解決方案 - 我通常會發現這種事情是設計的一種症狀,可以通過其他方式得到改善。
我會刪除編譯時檢查並使其成為運行時:
public bool DoSomething(IBase item)
{
var itemAdvanced = item as IAdvanced;
if (itemAdvanced != null)
return DoSomethingSpecific(itemAdvanced);
else
return DoSomethingSpecific(item);
}
原因是如果你的調用者只是靜態地知道對象是一個IBase
,但是在運行時它是一個IAdvanced
,不是首選將它當作IAdvanced
嗎? 這可能也是做你想做的最快的方式。 如果你看到需要,我只會采用dynamic
方法,例如因為可能存在大量不同的方法。
據他所知,這是一個IBase。 編譯器需要確定你調用哪種方法,這就是它總是選擇那個方法的原因。
一個骯臟的技巧將是這樣做:
public static bool DoSomething<T>(T item) where T: IBase
{
var isAdvanced = typeof(IAdvanced).IsAssignableFrom(typeof(T));
return isAdvanced ? DoSomethingSpecific((IAdvanced)item) : DoSomethingSpecific(item);
}
另一種方法是使用Double-Dispatch / Visitor模式:
public interface IDoSomethingVisitor {
bool DoSomethingSpecific(IBase base);
bool DoSomethingSpecific(IAdvanced adv);
}
DoSomething方法將在您的IBase界面中:
public interface IBase{
void DoSomething(IDoSomethingVisitor visitor);
}
在您的實施中:
public class Base : IBase
{
public bool DoSomething(IDoSomethingVisitor visitor)
{
visitor.DoSomething(this);
}
}
public class Advanced : IAdvanced
{
public bool DoSomething(IDoSomethingVisitor visitor)
{
visitor.DoSomething(this);
}
}
在這種情況下,使用純繼承解決問題。 實際的實例是解析調用哪個方法的實例。 不,如果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.