调用函数后,是否可以使用延迟加载函数参数?

时间:2016-02-04 19:09:34

标签: c# .net lazy-loading lazy-evaluation lazy-initialization

我想知道在调用函数后是否可能在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>没有做我需要的事情。有没有人知道支持这种情况的任何变通方法或语言功能?

3 个答案:

答案 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使其正常工作