我想知道是否可以在 C# 中延迟加载函数的参数在调用函数后。实际上,我希望仅在使用函数输出时才加载函数的参数。我尝试用以下示例解释我的意思:
var a = Enumerable.Range(1, 10);
int take = 5;
var lazyTake = new Lazy<int>(() => take);
// here I still don't iterate on Enumerable, I want the parameter of function Take be initialized later when I start iterating
var b = a.Take(lazyTake.Value);
// here I initialize (change) the value of parameter take
take = 6;
Console.WriteLine(b.ToList().Count); // I want b to have 6 elements but it's 5
在这里Lazy<int>
没有做我需要的。有谁知道任何解决方法或语言功能来支持这种情况?
public static IEnumerable<T> Take<T>(this IEnumerable<T> source, Lazy<int> count) {
var takeSequence = source.Take(count.Value);
foreach (var item in takeSequence) yield return item;
}
这完全是懒惰的。此函数的主体仅在开始枚举时执行,因为这是一个迭代器方法。只有这样,懒惰的count
才会被迫实现。
除了Lazy
,您还可以传递Func<int> getTakeCount
参数。
懒惰在您访问 .值属性。因此,在你调用a.Take的时候,你得到了实际的int值5。此时更改take
变量无济于事,懒惰消失了。
你需要一个函数 需要 Lazy<T>
,而不是T
。如果您了解如何实现IEnumerable<T>
,您可能可以轻松编写一个,但我知道的框架中没有任何内置内容可以适合您的场景。
一切都正确,值正在延迟初始化,但问题是当您调用 a.take(lazyTake.Value) 时正在评估该值,因为您将其作为参数传递给函数并且必须对其进行计算。
你能做的最好的事情就是用lambda包围它,并在最后执行lambda:
var a = Enumerable.Range(1, 10);
int take = 5;
// here I still don't iterate on Enumerable, I want the parameter of function Take be initialized later when I start iterating
Func<IEnumerable<int>> getResult = () => a.Take(take);
// here I initialize (change) the value of parameter take
take = 6;
Console.WriteLine(getResult().ToList().Count);
编辑:不能将var用于lambda,只需使用Func使其工作即可