我有以下扩展方法:
public static IEnumerable<XElement> GetElement(this XmlReader reader, string elementName)
{
reader.MoveToElement();
while (!reader.EOF)
{
if (reader.NodeType == XmlNodeType.Element
&& reader.Name.Equals(elementName))
{
yield return XNode.ReadFrom(reader) as XElement;
}
reader.Read();
}
}
public static IEnumerable<XElement> ExtractElement(this Stream stream, string elementName)
{
using (var reader = XmlReader.Create(stream))
{
return reader.GetElement(elementName));
}
}
然后我尝试打开FileStream
并使用以下内容获取XML
文件中的特定元素:
using (var stream = File.Open("My.xml", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
var element = stream.ExtractElement("subscriptionForms").First();
element.Elements("subscriptionForm").Count().ShouldBe(11);
}
然而,由于xml阅读器关闭(reader.EOF
为false
且reader.Read()
没有做任何事情),运行代码会导致无限循环,但是当我更改以下行时:< / p>
return reader.GetElement(elementName));
为:
foreach (var xElement in reader.GetElement(elementName, ignoreCase))
{
yield return xElement;
}
一切似乎都运转良好。为什么前一个实现会导致读者关闭?
答案 0 :(得分:1)
reader.GetElement(elementName)
尚未开始枚举。它返回一个对象,一旦你看它包含的内容,就开始从reader
读取。由于您直接返回该对象,return
语句包含在using
中,using
语句会导致读者在枚举开始之前关闭。
当您将其封装在foreach
循环中时,关闭阅读器的using
语句的效果会延迟到foreach
终止,到那时为止#39} ;没关系,到那时你不再需要读者了。