簡體   English   中英

重載C#中的通用接口參數

[英]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方法。 這是預期的行為嗎? 我不能僅在泛型中僅使用接口參數來重載嗎?

由於stringIEnumerable<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.

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