如果我想编写一个方法,它采用可变数量的"TDerived",其中TDerived是类"Base"的任何子类,有没有办法做到这一点?
以下代码仅适用于单个特定的指定子类:
void doStuff<TDerived>(params TDerived[] args) where TDerived : Base
{
//stuff
}
Run Code Online (Sandbox Code Playgroud)
即如果我有
class Super { }
class Sub0 : Super { }
class Sub1 : Super { }
Run Code Online (Sandbox Code Playgroud)
那我就做不到了
Sub0 s0 = new Sub0();
Sub1 s1 = new Sub1();
doStuff(s0, s1);
Run Code Online (Sandbox Code Playgroud)
因为我得到"最好的重载匹配......有一些无效的论点".
无论编译器如何处理类型约束和可变参数函数,这似乎(据我所知)完全类型安全.我知道我可以施放,但如果这是类型安全的,为什么不允许它?
编辑:
也许是一个更有说服力的例子:
void doStuff<TDerived>(params SomeReadOnlyCollection<TDerived>[] args) where TDerived : Base
{
foreach(var list in args)
{
foreach(TDerived thing in list)
{
//stuff
}
}
}
Run Code Online (Sandbox Code Playgroud)
在您的示例中,您实际上是告诉编译器在编译时所有参数doStuff必须是相同的类型,并且必须继承此类型Base.如果要允许参数具有不同的类型,那么就不要使用泛型:
void doStuff(params Base[] args)
{}
Run Code Online (Sandbox Code Playgroud)
编辑
这同样适用于您的新示例 - 而不是SomeReadOnlyCollection您可以使用的特定内容IEnumerable,因为它是协变的:
void doStuff(params IEnumerable<Base>[] args)
{
foreach (var list in args)
{
foreach (var thing in list)
{
}
}
}
Run Code Online (Sandbox Code Playgroud)
TDerived需要能够解析为单一类型.在您的示例中,它可以解析的唯一类型是Super,但编译器不会实现这一飞跃.您可以为编译器实现这一飞跃.
doStuff(new Super[] { s0, s1 });
doStuff<Super>(s0, s1);
Run Code Online (Sandbox Code Playgroud)
关于您的更新,请考虑(而不是通用方法)定义接受方法IEnumerable<ISuper>,它将支持派生类型,因为它IEnumerable<T>是协变的(从.NET 4开始).IEnumerable<T>也是固有的只读和前向,如果你有一个foreach循环完美.完整的工作示例:
class Program
{
static void Main()
{
var sub0s = new Sub0[] { new Sub0() };
var sub1s = new List<Sub1> { new Sub1() };
doStuff(sub0s, sub1s);
}
static void doStuff(params IEnumerable<ISuper>[] args)
{
foreach (var sequence in args)
{
foreach (var obj in sequence)
{
Console.WriteLine(obj.GetType());
// you have the ability to invoke any method or access
// any property defined on ISuper
}
}
}
}
interface ISuper { }
class Super : ISuper { }
class Sub0 : Super { }
class Sub1 : Super { }
Run Code Online (Sandbox Code Playgroud)
IEnumerable<T>由BCL集合因为.NET 2.0实施,包括T[],List<T>,ReadOnlyCollection<T>,HashSet<T>,等.