为什么 XmlReader 在返回 IEnumerable<T> 时关闭?

Why is the XmlReader getting closed when returning an IEnumerable<T>?

我有以下扩展方法:

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 关闭(reader.EOFfalsereader.Read() 什么也没做)但是当我更改以下行时:

return reader.GetElement(elementName));

至:

foreach (var xElement in reader.GetElement(elementName, ignoreCase))
{
    yield return xElement;
}

似乎一切正常。为什么前一个实现导致 reader 关闭?

reader.GetElement(elementName) 尚未开始枚举。它 return 是一个对象,一旦您查看它包含的内容,就会从 reader 开始读取。由于您直接 return 该对象,并且 return 语句包含在 using 中,因此 using 语句导致 reader 在枚举开始之前关闭.

当你将它包裹在 foreach 循环中时,using 语句关闭 reader 的效果会延迟到 foreach 终止,到那时它会好的,到时候你就不再需要 reader.