2016-04-28 10 views
0

私は、次の拡張メソッドを持っている:IEnumerable <T>を返すときにXmlReaderが閉じられるのはなぜですか?

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.EOFfalsereader.Read()は何もしていません)、次の行を変更すると:

return reader.GetElement(elementName)); 

へ:

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

すべてがうまく動作しているようです。なぜ前者の実装は読者を閉じさせるのですか?

+0

私はファイルの終わりを見つけるために 'reader.Read()'の戻り値を常にチェックしていましたが、もっと信頼できるかどうかわかりません( 'EOF 'プロパティtbh)。 –

+0

これは論理的なことですが、このケースでは私はできません:http://stackoverflow.com/questions/36909789/why-is-the-xmlreader-skipping-elements – babayi

+0

あなたは 'do {.. 。} while reader.Read(); 'あなたが望むなら、代わりに。 –

答えて

1

reader.GetElement(elementName)はまだ列挙されていません。それは、それが何を含んでいるかを見ると、readerから読み始めるオブジェクトを返します。そのオブジェクトを直接返し、returnステートメントがusingにラップされているため、usingステートメントは、列挙が開始される前にリーダーが閉じられるようにします。

あなたはforeachループでラップ

は、読者を閉じる using文の効果は foreach終了まで遅延され、その時点で、それはその時点であなたはもはやリーダーを必要としない、大丈夫でしょう。

関連する問題