为什么在foreach for XmlNode中使用的var不推导出实际类型,只推导出对象?

clsXmlNode类型

以下语句允许我访问子节点:

 foreach (XmlNode child in cls.ChildNodes) 

现在当我尝试使用var:

 foreach (var child in cls.ChildNodes) 

那么子类型不是XmlNode ,只是对象 。 我不能使用child.NodeType ,编译器说:

object’不包含’NodeType的定义

为什么是这样?

ChildNodes的类型为XmlNodeList ,定义为

 public abstract class XmlNodeList : IEnumerable, IDisposable 

它的枚举器返回一个object 。 当您使用XmlNode而不是var ,.net会自动casts对象castsXmlNode 。 但是当你使用var ,child被视为一个对象。

正如我最近发现的那样 ,foreach循环对元素变量的类型进行了显式强制转换。 这来自C#2.0之前的时间,其中引入了generics。

 List myList = getStringList(); foreach (string element in myList) { // ... } 

尽管myList只是一个List ,而不是generics,因此只包含对象,我知道它包含字符串,并且可以执行此foreach循环,这将为我添加显式强制转换。

输入generics。 突然间你不再需要它,但它仍然是语言的一部分。

 List myList = getStringList(); foreach (string element in myList) { // ... } 

然而,这现在可能有一个可怕的陷阱:

 List myLongList = getLongList(); foreach (int element in myLongList) { // ... } 

这将不会产生错误,没有警告,也没有运行时exception。 即使我在没有检查的情况下投入了多头。 我很有可能损坏了我的数据。 哎哟。 怎么避免这个?

通过使用var ,就像你一样。

 List myLongList = getLongList(); foreach (var element in myLongList) { // ... } 

现在,无论列表的元素类型是什么,我的element变量都是相同的类型。 好极了!

如果这不足,则使用非通用API,例如XmlNode 。 当您询问它的子节点时,您会得到一个非通用列表。 如果您现在使用var ,则系统无法知道此列表仅包含XmlNode实例。 实际上它所能做的就是采用非通用方式,并将该var转换为object

简而言之,您的第一个foreach语句可以正常工作,因为隐式显式转换(因为我已经在脑海中称之为)。 第二个失败,因为没有那个演员,没有类型信息而是object