[英]Overloading generic interface parameters in C#
我創建了以下課程:
class GenericTest
{
public T Do<T>( T test ) where T : class
{
return test;
}
public IEnumerable<T> Do<T>( List<T> test ) where T : class
{
return test;
}
public IEnumerable<T> Do<T>( IEnumerable<T> test ) where T : class
{
return test;
}
}
這具有Do()函數的三個重載。 我試圖了解方法參數匹配如何在C#中用於泛型,尤其是在接口參數周圍。 因此,我有以下測試程序:
static void Main( string[] args )
{
GenericTest testing = new GenericTest();
string s = "TEST";
List<string> list = new List<string> {s};
Stack<string> stack = new Stack<string>();
stack.Push( s );
testing.Do( s ); //calls public T Do<T>( T test )
testing.Do( list ); //calls IEnumerable<T> Do<T>( List<T> test )
testing.Do( stack ); //calls public T Do<T>( T test ) where T : class
}
對Do()的第一次調用按我的預期工作,然后具體的類List參數與List參數方法很好地匹配,但是當我傳遞IEnumerable時,編譯器不使用IEnumerable參數方法,而是選擇了通用T方法。 這是預期的行為嗎? 我不能僅在泛型中僅使用接口參數來重載嗎?
由於string
為IEnumerable<char>
我不確定第一次調用是否按預期方式工作...在這種情況下應執行哪個方法? 這取決於您的特定要求。
您描述的行為可以按照CoR模式靈活地實現,在CoR模式中,您可以根據特定需要定義匹配邏輯和鏈元素順序。
下面只是一個展示想法的圖示(我敢肯定它可以重構):
public abstract class ChainElem
{
public abstract bool IsMatching(object o);
public abstract void Do(object o);
}
public class ChainElemIList : ChainElem{
public override bool IsMatching(object o) {
//Matches IList implementations only.
if( o is IList )
return true;
else
return false;
}
public override void Do(object o) {
//Do something with the IList
Console.WriteLine("processing IList...");
}
}
public class ChainElemIEnumerable : ChainElem{
public override bool IsMatching(object o) {
//Matches all IEnumerable implementations(but not string).
//This is something that you won't achieve with generics.
if( o is IEnumerable && !(o is string) )
return true;
else
return false;
}
public override void Do(object o) {
//Do something with the IEnumerable(but not string)
Console.WriteLine("processing IEnumerable(but not string)...");
}
}
public class ChainElemString : ChainElem{
public override bool IsMatching(object o) {
//Matches strings only.
if( o is string )
return true;
else
return false;
}
public override void Do(object o) {
//Do something with the string
Console.WriteLine("processing string...");
}
}
public class ChainElemObject : ChainElem{
public override bool IsMatching(object o) {
//Matches everything else.
return true;
}
public override void Do(object o) {
//Do something with the object
Console.WriteLine("processing object...");
}
}
void Main()
{
string s = "TEST";
List<string> list = new List<string> {s};
Stack<string> stack = new Stack<string>();
stack.Push( s );
object o = new object();
//construct the chain - order is important and depends on your requirements
var chain = new List<ChainElem> {
new ChainElemIList(),
new ChainElemIEnumerable(),
new ChainElemString(),
new ChainElemObject()
};
//processing
chain.First(c => c.IsMatching(list)).Do(list);
chain.First(c => c.IsMatching(stack)).Do(stack);
chain.First(c => c.IsMatching(s)).Do(s);
chain.First(c => c.IsMatching(o)).Do(o);
//OUTPUT:
// processing IList...
// processing IEnumerable(but not string)...
// processing string...
// processing object...
}
因此,如果您具有與簽名匹配的通用方法,則似乎無法重載接口參數。
為您的方法使用其他名稱,或者在參數列表中使用具體的類。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.