在 foreach 循环中无法识别对象类型
本文关键字:识别 对象 类型 foreach 循环 | 更新日期: 2023-09-27 18:32:51
所以,我今天遇到了一个奇怪的问题。
假设我有一个定义如下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 的定义,并且找不到接受 ojbect 类型的第一个参数的扩展方法 ForeColor。
object不包含节点的定义,并且找不到接受 object 类型的第一个参数的扩展方法节点。
但是,如果我用TreeNode child
更改var child
,一切都按预期工作。
有人可以解释这种行为吗?
因为TreeNodeCollection
在object
上只有一个枚举器(它实现IEnumerable
,而不是IEnumerable<TreeNode>
(,所以var
变得object
。自己键入变量,您的代码将编译:
foreach (TreeNode child in nodes)
{ }
如其他答案所述,TreeNodeCollection
是object
对象的集合。这是因为WinForms从一开始就是C#语言(.NET 1.1(的一部分,并且直到.NET 2.0才添加泛型。出于向后兼容性的原因,他们没有更改类以实现IEnumerable<TreeNode>
。
正如您所发现的,处理它们的唯一方法是在foreach
循环中显式键入对象作为TreeNode
。这是因为var
直到 .NET 3.5 才添加。
另一种替代方法(尽管更详细(是获取所需类型的对象:
foreach (var child in nodes.OfType<TreeNode>())
正如我所说,这更详细,你更适合只显式强制转换对象。但是,OfType
方法在您的曲目中是一个很好的方法。
澄清
正如帕特里克回答的评论中提到的,另一种选择是.Cast<T>()
.但是,如果这样做,如果无法将项强制转换为指定类型,则会引发异常。在这种情况下,您很好,因为根据创建集合的方式,您不会有任何不是TreeNode
的东西。但是,在其他集合中,可以基于超类等具有其他类型。 OfType<T>()
将忽略不属于您请求的任何类型。
如果你在MSDN上看,你会看到这个:
public class TreeNodeCollection : IList, ICollection, IEnumerable
请注意,它不使用泛型集合,因此您必须使用变量类型而不是 var,因为将使用object
。
树节点集合类