问题描述
列表标签
:
集合< Label> labels = new Collection< Label>();
现在我想将它转换为 我会尝试调用: 但不能编译。 编译,但在运行时崩溃。 编译,但在运行时崩溃。 有没有办法绕过通用的对象列表? 另一种方法是放弃通用列表,并使用typed列表: 但是,这意味着所有使用泛型的代码都必须进行改进。 你不能施放它;您必须自己转换它。 您的问题在于 Controls $ c的集合
$ b $ pre $ public void ScaleControls(ICollection< Control> controls){}
ScaleControls标签);
ScaleControls((ICollection的<控制>)标签);
的ICollection<控制> controls =(ICollection< Control>)标签;
ScaleControls(c);
public class ControlList:Collection< Control>
{
}
pubic void InvalidateControls(ControlList控件)
{
}
InvalidateControls(新列表< Control>(labels)); // C#4或更高版本
ICollection< T>
不是协变的。 ICollection不协变的原因是为了防止像这样的方法变得邪恶:
$ b $ pre $ void AddControl(ICollection< Control> controls,Control控制)
{
controls.Add(control);
}
为什么会是邪恶的?因为如果ICollection是协变的,该方法将允许您将TextBox添加到标签列表中:
AddControl(new List< Label> (),new TextBox());
List< Control>
需要 IEnumerable< Control>
。为什么我们可以将标签
传递给?因为 IEnumerable< T>
是协变的:你不能将任何东西放到 IEnumerable< T>
你只能把东西拿出来。因此,您知道可以将任何从 IEnumerable< T>
中检索到的任何东西视为T(当然)或其任何基类型。
$ b
编辑
我刚刚注意到您正在使用.Net 3.5。在这种情况下, IEnumerable< T>
不是协变的,您需要更多代码才能转换集合。像这样:
ICollection< T> ConvertCollection< T,U>(ICollection< U> collection)其中U:T
{
var result = new List< T>(collection.Count);
foreach(集合中的var项)
result.Add(item);
}
Consider a list of Label
:
Collection<Label> labels = new Collection<Label>();
Now i want to cast this to a collection of Controls
:
public void ScaleControls(ICollection<Control> controls) {}
i would try calling:
ScaleControls(labels);
but that doesn't compile.
ScaleControls((ICollection<Control>)labels);
compiles, but crashes at runtime.
ICollection<Control> controls = (ICollection<Control>)labels;
ScaleControls(c);
compiles, but crashes at runtime.
Is there a way to pass around generic lists of objects?
The alternative is to abandon generic lists, and use typed lists:
public class ControlList : Collection<Control>
{
}
pubic void InvalidateControls(ControlList controls)
{
}
But that means all code using generics must be retrofitted.
You can't cast it; you have to convert it yourself.
InvalidateControls(new List<Control>(labels)); //C# 4 or later
Your problem here is that ICollection<T>
is not covariant. The reason ICollection is not covariant is to prevent methods like this from being evil:
void AddControl(ICollection<Control> controls, Control control)
{
controls.Add(control);
}
Why would that be evil? Because if ICollection were covariant, the method would allow you to add TextBoxes to lists of labels:
AddControl(new List<Label>(), new TextBox());
List<Control>
has a constructor that takes IEnumerable<Control>
. Why can we pass labels
in? Because IEnumerable<T>
is covariant: You can't put anything into an IEnumerable<T>
; you can only take things out. Because of that, you know that you can treat anything retrieved from the IEnumerable<T>
as a T (of course) or any of its base types.
EDIT
I just noticed that you're using .Net 3.5. In that case, IEnumerable<T>
is not covariant, and you'll need more code to convert the collection. Something like this:
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);
}
这篇关于如何将泛型集合转换为泛型集合的祖先?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!