【问题标题】:Overloading generic interface parameters in C#在 C# 中重载泛型接口参数
【发布时间】:2014-06-10 09:14:31
【问题描述】:

我创建了以下类:

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 方法。这是预期的行为吗?我不能只用泛型中的接口参数重载吗?

【问题讨论】:

标签: c# generics interface parameters


【解决方案1】:

我不确定第一次通话是否按预期工作,因为 stringIEnumerable&lt;char&gt; ... 在这种情况下应该执行哪种方法?这取决于您的特定要求。

您所描述的行为可以按照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...

}

【讨论】:

  • 感谢您的建议。 IEnumerable 调用根本不匹配。我确实考虑过使用反射来确定参数是否支持 IEnumerable,但实际上我希望编译器选择正确的方法。我认为 IEnumerable 调用可能永远不会匹配,但我觉得编译器应该根据两种匹配的方法类型发出警告或错误,而不是选择一种。
【解决方案2】:

所以,如果你有与签名匹配的泛型方法,你似乎不能用接口参数重载。

为您的方法使用不同的名称,或在参数列表中使用具体的类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-22
    • 2022-06-11
    • 2022-01-26
    相关资源
    最近更新 更多