我正在研究一种查找配置文件路径的方法。这需要做两遍:首先找到任何现有的配置文件,然后向后查找第一个可写路径。
虽然对我的特殊情况来说有点过分了,但这让我开始思考:是否可以同时进行惰性求值和防止多重枚举?
为了说明我的意思,请考虑以下代码:
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 一部分的意义上来说,这不是内置的,而是“现成的”。
然后添加
using MoreLinq.Experimental;
将示例更改为:
var paths = GetPaths().Memoize();
它将产生所需的输出。
请注意 morelinq 确实考虑了 Memoize
成为“实验性的”,FWIW。
关于c# - 是否可以缓存 IEnumerable 惰性评估结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39575925/