2011-06-17 13 views
2

私は.NETの開発者であり、最近ruby_koansでRubyを学び始めました。 Rubyのシンタックスのいくつかはすばらしく、そのうちの1つが「サンドイッチ」コードを処理する方法です。Rubyのサンドイッチブロックコードに相当するC#式。

以下は、ルビーサンドイッチコードです。

def file_sandwich(file_name) 
    file = open(file_name) 
    yield(file) 
    ensure 
    file.close if file 
    end 

    def count_lines2(file_name) 
    file_sandwich(file_name) do |file| 
     count = 0 
     while line = file.gets 
     count += 1 
     end 
     count 
    end 
    end 

    def test_counting_lines2 
    assert_equal 4, count_lines2("example_file.txt") 
    end 

は私が面倒「ファイルのオープンとクローズコード」私は、ファイルへのアクセスが、任意のC#の同等のコードを考えることはできませんたびに取り除くことができることを魅了しています。たぶん、IoCの動的プロキシを使って同じことをすることはできますが、C#で純粋に行うことができる方法はありますか?

事前に感謝します。

答えて

8

あなたは確かにIoC関連のものは必要ありません。どの程度:それはあまり助けにはならない。この場合

public T ActOnFile<T>(string filename, Func<Stream, T> func) 
{ 
    using (Stream stream = File.OpenRead(stream)) 
    { 
     return func(stream); 
    } 
} 

public int CountLines(string filename) 
{ 
    return ActOnFile(filename, stream => 
    { 
     using (StreamReader reader = new StreamReader(stream)) 
     { 
      int count = 0; 
      while (reader.ReadLine() != null) 
      { 
       count++; 
      } 
      return count; 
     } 
    }); 
} 

、すでに何をしたいの大半を行います...しかし、一般的な原則が成り立つusing文として。確かに、LINQの柔軟性はそういうものです。あなたがLINQをまだ見ていないなら、私は強くお勧めします。

public int CountLines(string filename) 
{ 
    return File.ReadLines(filename).Count(); 
} 

注これはまだ一度にラインを読みます...しかしCount拡張メソッドが返された配列に作用すること:ここで

は、私が使用したい行為CountLines方法です。

.NET 3.5では、それは次のようになります。

public int CountLines(string filename) 
{ 
    using (var reader = File.OpenText(filename)) 
    { 
     int count = 0; 
     while (reader.ReadLine() != null) 
     { 
      count++; 
     } 
     return count; 
    } 
} 

...まだかなりシンプル。

+0

多くのありがとう。私はサンドイッチのコードを処理するC#の方法を探していましたが、これはそれです。 – Andy

3

ストリームを開いたり閉じたりするだけのものを探していますか?

public IEnumerable<string>GetFileLines(string path) 
{ 
    //the using() statement will open, close, and dispose your stream for you: 
    using(FileStream fs = new FileStream(path, FileMode.Open)) 
    { 
     //do stuff here 
    } 
} 
0

yield returnあなたが探しているのは?

usingは、閉じ括弧に達した時点でDispose()とClose()を呼び出しますが、この特定のコード構造をどのように達成するかが問題です。

編集:ちょうどこれがあなたが探しているものではないことに気付きましたが、多くの人がこの手法を知らないので、私はここで答えを残します。

static IEnumerable<string> GetLines(string filename) 
{ 
    using (var r = new StreamReader(filename)) 
    { 
     string line; 
     while ((line = r.ReadLine()) != null) 
      yield return line; 
    } 
} 

static void Main(string[] args) 
{ 
    Console.WriteLine(GetLines("file.txt").Count()); 

    //Or, similarly: 

    int count = 0; 
    foreach (var l in GetLines("file.txt")) 
     count++; 
    Console.WriteLine(count); 
}