获得IEnumerable的第一项,并将其余部分作为IEnumerable返回,仅迭代一次

问题描述 投票:1回答:1

我有一个枚举,其中包含来自服务调用的响应,这些响应逐渐出现。

  • 我无法对可枚举执行ToList,因为那样会阻塞,直到收到所有响应,而不是在它们出现时列出它们。
  • 我也不能重复两次,因为这会触发另一个服务调用。

如何获取可枚举中的第一个元素并返回可枚举的延续?出现编译错误时,我无法使用迭代器方法:

迭代器不能具有ref,in或out参数。

我已经尝试过此代码:

public IEnumerable<object> GetFirstAndReturn(IEnumerable<object> enumerable, out object first)
{
      first = enumerable.Take(1).FirstOrDefault();
      return enumerable.Skip(1);  // Second interation - unexceptable
}


// This one has a compilation error: Iterators cannot have ref, in or out parameters
public IEnumerable<object> GetFirstAndReturn2(IEnumerable<object> enumerable, out object first)
{
    var enumerator = enumerable.GetEnumerator();
    first = enumerator.Current;
    while (enumerator.MoveNext())
    {
        yield return enumerator.Current;
    }
}
c# ienumerable enumerate enumerator
1个回答
1
投票

代替使用out参数,可以使用ValueTuple<T1, T2>(从C#7.0起,已记录在here中)返回两个元素:IEnumerable<T>的第一项,其余的作为另一个IEnumerable<T>

using System.Linq;

class Program {
    static void Main(string[] args) {
        (int first, IEnumerable<int> remainder) = GetFirstAndRemainder(Enumerable.Range(1, 5));
        // first = 1
        // remainder yields (2, 3, 4, 5)
    }

    // Returns the first item and the remainders as an IEnumerable
    static (T, IEnumerable<T>) GetFirstAndRemainder<T>(IEnumerable<T> sequence) {
        var enumerator = sequence.GetEnumerator();
        enumerator.MoveNext();
        return (enumerator.Current, enumerator.AsEnumerable());
    }
}

您还需要使用扩展方法将IEnumerator转换为IEnumerable

static class Extensions {
    public static IEnumerable<T> AsEnumerable<T>(this IEnumerator<T> enumerator) {
        while (enumerator.MoveNext()) {
            yield return enumerator.Current;
        }
    }
}

请注意,根据您的要求,即使remainder的类型为IEnumerable<T>,对其进行一次迭代也会耗尽它。

© www.soinside.com 2019 - 2024. All rights reserved.