TextReaderのClose
昨日、数時間悩んだこと。
using System; using System.IO; using System.Collections.Generic; class Program { static public void Main(string[] args) { Console.WriteLine("From string:"); TestBehavior(FromString("hello")); Console.WriteLine(""); Console.WriteLine(""); Console.WriteLine("Close reader outside method:"); TextReader reader1 = new StringReader("hello"); TestBehavior(WithoutClose(reader1)); reader1.Close(); Console.WriteLine(""); Console.WriteLine(""); Console.WriteLine("Close reader inside method:"); TextReader reader2 = new StringReader("hello"); TestBehavior(WithClose(reader2)); Console.WriteLine(""); } static void TestBehavior(IEnumerable<string> co) { Console.WriteLine("1st:"); foreach (string s in co) { Console.Write(s + " "); } Console.WriteLine(""); Console.WriteLine("2nd:"); foreach (string s in co) { Console.Write(s + " "); } } static IEnumerable<string> FromString(string source) { TextReader reader = new StringReader(source); int tmp = -1; while (-1 != (tmp = reader.Read())) { char ch = (char)tmp; yield return ch.ToString(); } reader.Close(); } static IEnumerable<string> WithoutClose(TextReader reader) { int tmp = -1; while (-1 != (tmp = reader.Read())) { char ch = (char)tmp; yield return ch.ToString(); } } static IEnumerable<string> WithClose(TextReader reader) { int tmp = -1; while (-1 != (tmp = reader.Read())) { char ch = (char)tmp; yield return ch.ToString(); } reader.Close(); } }
実行すると
From string: 1st: h e l l o 2nd: h e l l o Close reader outside method: 1st: h e l l o 2nd: Close reader inside method: 1st: h e l l o 2nd: Unhandled Exception: System.ObjectDisposedException: Cannot read from a closed StringReader at System.IO.StringReader.CheckObjectDisposedException () [0x00000] in <filename unknown>:0 at System.IO.StringReader.Read () [0x00000] in <filename unknown>:0 at Program+<WithClose>c__Iterator1.MoveNext () [0x00000] in <filename unknown>:0 at Program.TestBehavior (IEnumerable`1 co) [0x00000] in <filename unknown>:0 at Program.Main (System.String[] args) [0x00000] in <filename unknown>:0
1番目のような挙動を期待していたけど、2番目のように書いててイテレータの挙動に悩んだ。最後は論外。