我想知道在调用函数后是否可能在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>
没有做我需要的事情。有没有人知道支持这种情况的任何变通方法或语言功能?
答案 0 :(得分:3)
public 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
。
答案 1 :(得分:1)
Lazy在您访问.Value属性时意识到它的价值。所以当你调用a.Take时,你已经得到了实际的int值5.改变take
变量在这一点上没有用,懒惰就消失了。
您需要的功能需要Lazy<T>
,而不是T
。如果你了解如何实现IEnumerable<T>
,你可以写一个没有太多麻烦的,但是我知道的框架没有内置任何东西适合你的场景。
答案 2 :(得分:0)
一切都是正确的,值是懒惰地初始化,但问题是当你调用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使其正常工作