この記事は、IEnumerable<T>
の実装を理解を深めるために書いたものです。
TextReaderを列挙可能にする
.NET Frameworkには、File.ReadLinesというメソッドが用意されているのですが、入力がファイルに限定されています。しかし、今回作成する簡易catコマンドは、標準入力もサポートしたいので利用できません。
ということで、IEnumerable<T>
を実装したEnumerableTextReaderクラスを作成しました。TextReaderオブジェクトから行を順に列挙するクラスです。
汎用性を持たせるために、テキスト形式のStreamも扱えるようにします。
以下、EnumerableTextReaderクラスのソースコードです。
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
namespace Cat {
public class EnumerableTextReader : IEnumerable<string> {
private TextReader _sr;
public EnumerableTextReader(TextReader tr) => _sr = tr;
public EnumerableTextReader(Stream s) => _sr = new StreamReader(s);
public IEnumerator<string> GetEnumerator() {
string s;
while ((s = _sr.ReadLine()) != null) {
yield return s;
}
}
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
}
}
このクラスは、IEnumerable<T>
インターフェースを実装していますので、テキストファイルに対して、LINQの拡張メソッドが利用できるようになります。とは言っても、簡易catコマンドではLINQのメソッドは利用してないですが...
TextReaderを受け取るコンストラクタを用意していますので、Console.In
を渡せば、標準入力からも行単位で入力データを列挙することができます。
簡易catコマンドを実装する
上記のEnumerableTextReaderクラスを使って、簡易catコマンドを書いてみました。
このプログラムは、標準入力からデータを読み込み、標準出力に書きだすだけの簡単なものです。
使い方は以下のような感じ。
C:\>cat < sample.txt > sample2.txt
これで、sample.txtの内容を、sample2.txtに複写することができます。
以下のようなcatコマンド名だけの場合、キーボードから入力した行をそのままコンソール画面に表示します。この場合は、Ctrl+Zで入力を終了させます。
C:\>cat
以下、EnumerableTextReaderクラスを利用した簡易catコマンドのソースコードです。
using System;
using System.Linq;
using System.Collections.Generic;
namespace Cat {
class Program {
static void Main() {
var reader = new EnumerableTextReader(Console.In);
reader.ForEach(Console.WriteLine);
}
}
public static class EnumerableExtentions {
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) {
foreach (T x in source) {
action(x);
}
}
}
}
補足
このコード、.NET Core 2.0でも動作確認しています。
ソースは、GitHubで公開しています。
この記事は、Gushwell's C# Programming Pageで公開したものを加筆・修正したものです。