Help us understand the problem. What is going on with this article?

C#:IEnumerable<T>の実装サンプルとして簡易catコマンドを作成してみた

More than 1 year has passed since last update.

この記事は、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で公開したものを加筆・修正したものです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした