延迟检索用作 IEnumerable 的数组

Ale*_*øst 1 c#

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

T[] Get();
Run Code Online (Sandbox Code Playgroud)

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

IEnumerable<T2> GetProjected(); 
Run Code Online (Sandbox Code Playgroud)

现在,我意识到我无能为力让自己变得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));
}
Run Code Online (Sandbox Code Playgroud)

你可能会明白我的意思。如何在IEnumerable<T2>不立即调用的情况下公开Get()?我是否必须实现自定义IEnumerator<T2>IEnumerable<T2>配对?

Mo *_* B. 5

使用迭代器方法:

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

   foreach(var x in results) 
   {
        yield return x;
   }
}
Run Code Online (Sandbox Code Playgroud)

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

  • @AlexanderHøst 不,它不会立即执行`Get()`。尝试一下。 (4认同)