c# - 是否可以缓存 IEnumerable 惰性评估结果?

标签 c# ienumerable lazy-evaluation

我正在研究一种查找配置文件路径的方法。这需要做两遍:首先找到任何现有的配置文件,然后向后查找第一个可写路径。

虽然对我的特殊情况来说有点过分了,但这让我开始思考:是否可以同时进行惰性求值和防止多重枚举?

为了说明我的意思,请考虑以下代码:

public IEnumerable<string> GetPaths()
{
    Console.WriteLine("GetPaths() Returning 'one'");
    yield return "one";
    Console.WriteLine("GetPaths() Returning 'two'");
    yield return "two";
    Console.WriteLine("GetPaths() Returning 'three'");
    yield return "three";
}

public bool IsWritable(string path) => false; // testing only 

如果我运行:

var paths = GetPaths();
Console.WriteLine("Searching for existing file..");
foreach (var path in paths)
{
    if (File.Exists(path))
    {
        Console.WriteLine($"Found existing file '{path}'");
    }
}

Console.WriteLine("Searching for a writable path..");
foreach (var path in paths.Reverse()) // NOTE: paths enumarated twice
{
    if (IsWritable(path))
    {
        Console.WriteLine($"Found writable path '{path}'");
    }
}

Console.WriteLine("No paths found");

如果文件 'one' 存在,我们得到:

Searching for existing file..
Returning 'one'
Found existing file 'one'

但是,如果不存在任何文件,我们将得到:

Searching for existing file..
Returning 'one'
Returning 'two'
Returning 'three'
Searching for a writable path..
Returning 'one'
Returning 'two'
Returning 'three'
No paths found

(我们浪费地枚举了两次 GetPaths() 的结果)


一个简单的修复方法是将第一行更改为:

var paths = GetPaths().ToList();

但是,这意味着即使文件 one 存在,输出也将是:

Returning 'one'
Returning 'two'
Returning 'three'
Searching for existing file..
Found existing file 'one'

(例如,我们不必要地枚举列表的其余部分)


是否有一种(内置的)方法既能获得惰性枚举又能防止多重枚举?

换句话说,当'one'存在时期望的输出是:

Searching for existing file..
Returning 'one'
Found existing file 'one'

如果没有文件存在:

Searching for existing file..
Returning 'one'
Returning 'two'
Returning 'three'
Searching for a writable path..
No paths found

最佳答案

从成为 .NET 一部分的意义上来说,这不是内置的,而是“现成的”。

使用Nuget安装morelinq (package)。

然后添加

using MoreLinq.Experimental;

将示例更改为:

var paths = GetPaths().Memoize();

它将产生所需的输出。

请注意 morelinq 确实考虑了 Memoize成为“实验性的”,FWIW。

关于c# - 是否可以缓存 IEnumerable 惰性评估结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39575925/

相关文章:

c# - 多列多对一

C# 字符串解析为变量类型

c# - 如何创建单例 IEnumerable?

class - 让我的 getter 方法更改存储的值是不好的做法吗?

entity-framework - NHibernate 中的 Lazy 是什么意思

c# - 有条件地添加 CSS 类 - Asp.net

c# - VB.NET和C#的语法比较系统、全面、完整

c# 将字符串转换为 IEnumerable<T>

c# - 复制 IEnumerable,替换一个项目

c++ - 将特化添加到单 header "library"