繁体   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