C#表达式,相当于ruby的三明治块代码

And*_*ndy 2 c# ruby block

我是.NET开发人员,最近开始用ruby_koans学习ruby.Ruby的一些语法是惊人的,其中之一是它处理"三明治"代码的方式.

以下是红宝石三明治代码.

  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
Run Code Online (Sandbox Code Playgroud)

我很着迷,每次访问文件时我都可以摆脱繁琐的"文件打开和关闭代码"但却无法想到任何C#等效代码.也许,我可以使用IoC的动态代理来做同样的事情,但有什么方法我可以纯粹用C#做到这一点?

提前谢谢了.

Jon*_*eet 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;
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,它没有多大帮助,因为using声明已经完成了你想要的大部分......但是一般原则成立.实际上,这就是LINQ如此灵活的方式.如果你还没有看过LINQ,我强烈建议你这样做.

这是我使用的行为 CountLines方法:

public int CountLines(string filename)
{
    return File.ReadLines(filename).Count();
}
Run Code Online (Sandbox Code Playgroud)

请注意,这仍然只能一次读取一行...但Count扩展方法对返回的序列起作用.

在.NET 3.5中它将是:

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

...还是很简单.