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

Bar*_*icz 4 c# ienumerable enumerate enumerator

我有一个枚举,其中包含逐渐传入的服务调用的响应。

  • 我无法ToList对可枚举进行操作,因为这会阻塞,直到收到所有响应,而不是在收到响应时列出它们。
  • 我也无法迭代两次,因为这会触发另一个服务调用。

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

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

我试过这段代码:

public IEnumerable<object> GetFirstAndRemainder(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> GetFirstAndRemainder2(IEnumerable<object> enumerable, out object first)
{
    var enumerator = enumerable.GetEnumerator();
    enumerator.MoveNext();
    first = enumerator.Current;
    while (enumerator.MoveNext())
    {
        yield return enumerator.Current;
    }
}
Run Code Online (Sandbox Code Playgroud)

Cor*_*ane 5

out您可以使用ValueTuple<T1, T2>(从 C# 7.0 开始,在此处记录)返回两个元素,而不是使用参数: 的第一项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());
    }
}
Run Code Online (Sandbox Code Playgroud)

您还需要从 an 转换IEnumerator为 anIEnumerable我使用扩展方法所做的:

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

请注意,由于您的要求,remainder即使它的类型为 ,迭代一次也会耗尽它IEnumerable<T>