考虑 Label 列表:
Collection<Label> labels = new Collection<Label>();
现在我想将其转换为 Controls 的集合:
public void ScaleControls(ICollection<Control> controls) {}
我会尝试调用:
ScaleControls(labels);
但这不能编译。
ScaleControls((ICollection<Control>)labels);
编译,但在运行时崩溃。
ICollection<Control> controls = (ICollection<Control>)labels;
ScaleControls(c);
编译,但在运行时崩溃。
有没有办法传递对象的通用列表?
另一种方法是放弃通用列表,并使用类型化列表:
public class ControlList : Collection<Control>
{
}
pubic void InvalidateControls(ControlList controls)
{
}
但这意味着必须改造所有使用泛型的代码。
请您参考如下方法:
你不能施放它;你必须自己转换它。
InvalidateControls(new List<Control>(labels)); //C# 4 or later
你的问题是 ICollection<T>不是协变的。 ICollection 不是协变的原因是为了防止像这样的方法是邪恶的:
void AddControl(ICollection<Control> controls, Control control)
{
controls.Add(control);
}
为什么那是邪恶的?因为如果 ICollection 是协变的,该方法将允许您将 TextBox 添加到标签列表中:
AddControl(new List<Label>(), new TextBox());
List<Control>有一个采用 IEnumerable<Control> 的构造函数.为什么我们可以通过labels在?因为IEnumerable<T>是协变的:你不能将任何东西放入 IEnumerable<T> ;你只能把东西拿出来。因此,您知道您可以处理从 IEnumerable<T> 中检索到的任何内容作为 T(当然)或其任何基本类型。
编辑
我刚刚注意到您使用的是 .Net 3.5。在这种情况下,IEnumerable<T>不是协变的,您将需要更多代码来转换集合。像这样:
ICollection<T> ConvertCollection<T, U>(ICollection<U> collection) where U : T
{
var result = new List<T>(collection.Count);
foreach (var item in collection)
result.Add(item);
}
