在foreach循环中无法识别对象类型

时间:2016-02-02 14:35:38

标签: c# winforms

所以,我今天遇到了一个奇怪的问题。

假设我的TreeNode定义如下:

TreeNode node = new TreeNode();
node.Nodes.Add(new TreeNode { Name = "aaa" });
node.Nodes.Add(new TreeNode { Name = "bbb" });

然后我调用递归方法

ColorNode(node.Nodes, Color.Green);

方法如下:

void ColorNode(TreeNodeCollection nodes, System.Drawing.Color Color)
{
    foreach (var child in nodes)
    {
        child.ForeColor = Color;
        if (child.Nodes != null && child.Nodes.Count > 0)
            ColorNode(child.Nodes, Color);
    }
}

foreach循环中,如果我保持var child Visual Studio会发出

的话
  

对象不包含ForeColor的定义,也没有扩展方法ForeColor可以找到类型为ojbect的第一个参数。

     

对象不包含节点的定义,也没有扩展方法可以找到接受类型为object的第一个参数的节点。

但如果我用var child更改TreeNode child,一切都会按预期进行。

有人可以解释这种行为吗?

3 个答案:

答案 0 :(得分:7)

由于TreeNodeCollection仅在object上有一个枚举器(它实现了IEnumerable,而不是IEnumerable<TreeNode>),var变为object。自己键入变量,代码将编译:

foreach (TreeNode child in nodes)
{ }

答案 1 :(得分:2)

正如其他答案中所述,TreeNodeCollectionobject个对象的集合。这是因为WinForms从一开始就是C#语言的一部分(.NET 1.1),并且在.NET 2.0之前不会添加泛型。出于向后兼容性的原因,他们没有改变类以实现IEnumerable<TreeNode>

正如您所发现的,处理它们的唯一方法是在TreeNode循环中明确键入foreach对象。这是因为在.NET 3.5之前没有添加var

另一个替代方案(虽然更详细)是获取所需类型的对象:

foreach (var child in nodes.OfType<TreeNode>())

正如我所说,这更加冗长,你更适合于明确地投射对象。但是,OfType方法在您的保留曲目中是一个很好的方法。

<强>澄清

正如Patrick对答案的评论中提到的,另一种选择是.Cast<T>()。但是,如果这样做,如果项目无法转换为指定类型,则抛出异常。在这样的情况下,你没事,因为根据创建集合的方式,你不会有任何不是TreeNode的东西。但是,在其他集合中,可以使用基于超类等的其他类型。OfType<T>()将忽略任何不属于您请求类型的内容。

答案 2 :(得分:1)

如果您查看MSDN,您会看到:

public class TreeNodeCollection : IList, ICollection, IEnumerable

请注意,它没有使用泛型集合,因此您必须使用变量类型而不是var,因为将使用object

TreeNodeCollection Class