为什么var推断类型对象而不是XmlNodeList循环中的XmlNode?

时间:2012-02-03 10:28:22

标签: c# xml type-inference

如果有人像这样循环遍历XmlNodeList

foreach (XmlNode foo in xmlNodeList) {string baa = foo.Attributes["baa"].Value;}

一切都按预期工作 - foo显然是 XmlNode 类型,VS.NET IDE显示方法和字段。

另一方面

foreach (var foo in xmlNodeList) { string baa = foo.Attributes["baa"].Value; }

没有编译,因为这里的foo是 object 类型。键入推断类型的工作,但推断对象

显然,XmlNodeList的元素不是一个定义的类型,但是将它们分配给XmlNode而不是var会隐式地执行某些操作(强制转换或取消装箱)。

第一个问题:背后的机制是什么?

第二个(相关)问题:如何找到可以在这种循环中使用的类型? VS.NET IDE有帮助吗?

3 个答案:

答案 0 :(得分:9)

XmlNodeList仅实现非通用IEnumerable接口,而不是IEnumerable<XmlNode>类似于泛型的接口。这样可以防止对元素进行强类型操作,直到您进行适当的转换,因此编译器别无选择,只能将隐式类型声明映射到foreach中的object

如果您坚持使用var关键字,则可以像这样投射xmlNodeList的元素:

foreach (var foo in xmlNodeList.Cast<XmlNode>())
{
    string baa = foo.Attributes["baa"].Value;
}

但这很难看,无论如何都需要更多的击键。您也可以明确声明XmlNode foo,并让foreach随时为您投射。

答案 1 :(得分:4)

正如BoltClock所说,XmlNodeList只实现IEnumerable

foreach循环会在幕后自动为您投射,所以:

List<object> values = new List<object> { "x", "y", "z" };
foreach (string x in values)
{
    ...
}

完全合法,并且对每个值执行强制转换(当然可以抛出异常)。

我不清楚你的第二个问题是什么意思 - 但我建议你在循环中明确使用XmlNode。如果确实想要使用var,您可以写:

foreach (var foo in xmlNodeList.Cast<XmlNode>())

但这对我来说太过分了......

答案 2 :(得分:4)

在支持泛型之前,

XmlNodeList已经在.NET Framework中。因此,它仅实现非通用接口IEnumerable而不是通用IEnumerable<T> 要了解此列表中可以包含哪些类型,您需要阅读文档。最好的方法是indexer

BTW:自从Visual Studio 2005发布以来,IDE还没有被称为VS.NET :-)从那时起它就被称为VS.