首页 > 解决方案 > 懒惰地检索用作 IEnumerable 的数组

问题描述

我可以访问一个公开数组的 API T,即有一个签名

T[] Get();

我正在创建一个对Ts 执行计算并生成的 API T2。每次调用 to都是昂贵的,而从to的Get()每个投影都是昂贵的。我可能不需要所有的 s,所以我想公开:TT2T2

IEnumerable<T2> GetProjected(); 

现在,我意识到没有什么可以让我变得Get()懒惰。我将需要检索整个数组。但是,我希望能够在没有立即导致被调用的情况下调用GetProjected()并获得一个。换句话说,以下两种实现是不好的:IEnumerable<T2>Get()

public IEnumerable<T2> GetProjected()
{
    var items = _api.Get(); // bad!

    return items.Select(t => ProjectToT2(t));
}

public IEnumerable<T2> GetProjected2()
{
    var items = new Lazy<IEnumerable<T>(() => _api.Get());

    return items
        .Value // bad again!
        .Select(t => ProjectToT2(t));
}

你可能会看到我要去哪里。如何在IEnumerable<T2>不引起立即调用的情况下公开一个Get()?我必须实现自定义IEnumerator<T2>IEnumerable<T2>配对吗?

标签: c#

解决方案


使用迭代器方法:

public IEnumerable<T2> GetProjected()
{   
   var results = api.Get()
        .Select(t => ProjectToT2(t));

   foreach(var x in results) 
   {
        yield return x;
   }
}

由于 的签名,您无法绕过在一个完整块中检索的数组Get(),但是这样只有在枚举 的结果时才会调用它GetProjected(),例如,如果您调用ToArray()它,而不是使用Select()or Where


推荐阅读