これをまとめただけなので、非常に堅牢ではありませんが (エラー処理がないなど)、基本的なテスト ケースは機能します。
の拡張メソッドを作成することで機能しTextReader
、1 秒かかる新しい TextReader クラスを返します。このクラスはRead()
、最初のメソッドがなくなるまで内部的に呼び出し、次にRead()
2 番目のメソッドの呼び出しを開始します。これを無期限に連鎖させることができます。
の完全な実装を提供するには、 、、およびTextReader
を実装するだけで済みます。他のすべてのメソッドは、特定の実装に依存して動作します。したがって、以下に示すように、独自のものを作成することはそれほど悪くありません。Read()
Peek()
Close()
Dispose()
Read()
TextReader
これにより、既存の TextReader をラップするだけで、実際にそれらを呼び出して連結を実行するわけではないため、パフォーマンスの問題も軽減されます。
class Program
{
static void Main(string[] args)
{
StringReader first = new StringReader("hello ");
StringReader second = new StringReader("world");
StringReader third = new StringReader("!");
using (var allOfThem = first.Concat(second).Concat(third))
{
//writes "hello world!"
Console.WriteLine(allOfThem.ReadToEnd());
}
Console.Read();
}
}
public static class Extensions
{
public static TextReader Concat(this TextReader first, TextReader second)
{
return new ChainedTextReader(first, second);
}
private class ChainedTextReader : TextReader
{
private TextReader first;
private TextReader second;
private bool readFirst = true;
public ChainedTextReader(TextReader first, TextReader second)
{
this.first = first;
this.second = second;
}
public override int Peek()
{
if (readFirst)
{
return first.Peek();
}
else
{
return second.Peek();
}
}
public override int Read()
{
if (readFirst)
{
int value = first.Read();
if (value == -1)
{
readFirst = false;
}
else
{
return value;
}
}
return second.Read();
}
public override void Close()
{
first.Close();
second.Close();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
first.Dispose();
second.Dispose();
}
}
}
}