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

发布于 2024-11-15 21:25:47 字数 628 浏览 2 评论 0原文

我是一名 .NET 开发人员,最近开始使用 ruby​​_koans 学习 ruby​​。 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

我很着迷的是,每次访问文件时我都可以摆脱繁琐的“文件打开和关闭代码”,但想不出任何 C# 等效代码。也许,我可以使用 IoC 的动态代理来做同样的事情,但是有什么办法可以纯粹用 C# 来做呢?

非常感谢。

I am a .NET developer and recently started learning ruby with ruby_koans. Some of Ruby's syntaxes are amazing and one of them is the way it handles "Sandwich" code.

The following is ruby sandwich code.

  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

I am fascinated that I can get rid of the cumbersome "file open and close code" each time I access a file but cannot think of any C# equivalent code. Maybe, I can use IoC's dynamic proxy to do the same thing, but is there any way I can do it purely with C#?

Many thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

清风疏影 2024-11-22 21:25:47

这里你当然不需要任何与 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,我强烈建议您查看一下。

这是我使用的 act CountLines 方法:

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

请注意,这仍然一次只能读取一行...但是 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;
    }
}

...仍然非常简单。

You certainly don't need anything IoC-related here. How about:

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;
        }
    });
}

In this case it doesn't help very much, as the using statement already does most of what you want... but the general principle holds. Indeed, that's how LINQ is so flexible. If you haven't looked at LINQ yet, I strongly recommend that you do.

Here's the act CountLines method I'd use:

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

Note that this will still only read a line at a time... but the Count extension method acts on the returned sequence.

In .NET 3.5 it would be:

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

... still pretty simple.

揽月 2024-11-22 21:25:47

您是否只是在寻找可以为您打开和关闭流的东西?

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
    }
}

are you just looking for something that opens and closes the stream for you?

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
    }
}
往昔成烟 2024-11-22 21:25:47

收益回报是您想要的吗?

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);
}

Is yield return what you're looking for?

using will call Dispose() and Close() when it reaches the closing brace, but I think the question is how to achieve this particular structure of code.

Edit: Just realized that this isn't exactly what you're looking for, but I'll leave this answer here since a lot of people aren't aware of this technique.

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文