[英]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.