简体   繁体   English

.NET有多个集合的内置IEnumerable吗?

[英]Does .NET have a built in IEnumerable for multiple collections?

I need an easy way to iterate over multiple collections without actually merging them, and I couldn't find anything built into .NET that looks like it does that. 我需要一种简单的方法来迭代多个集合而不实际合并它们,我找不到任何内置于.NET中的内容。 It feels like this should be a somewhat common situation. 感觉这应该是一种常见的情况。 I don't want to reinvent the wheel. 我不想重新发明轮子。 Is there anything built in that does something like this: 有什么内置的东西是这样的:

public class MultiCollectionEnumerable<T> : IEnumerable<T>
{
    private MultiCollectionEnumerator<T> enumerator;
    public MultiCollectionEnumerable(params IEnumerable<T>[] collections)
    {
        enumerator = new MultiCollectionEnumerator<T>(collections);
    }

    public IEnumerator<T> GetEnumerator()
    {
        enumerator.Reset();
        return enumerator;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        enumerator.Reset();
        return enumerator;
    }


    private class MultiCollectionEnumerator<T> : IEnumerator<T>
    {
        private IEnumerable<T>[] collections;
        private int currentIndex;
        private IEnumerator<T> currentEnumerator;

        public MultiCollectionEnumerator(IEnumerable<T>[] collections)
        {
            this.collections = collections;
            this.currentIndex = -1;
        }

        public T Current
        {
            get
            {
                if (currentEnumerator != null)
                    return currentEnumerator.Current;
                else
                    return default(T);
            }
        }

        public void Dispose()
        {
            if (currentEnumerator != null)
                currentEnumerator.Dispose();
        }

        object IEnumerator.Current
        {
            get
            {
                return Current;
            }
        }

        public bool MoveNext()
        {
            if (currentIndex >= collections.Length)
                return false;
            if (currentIndex < 0)
            {
                currentIndex = 0;
                if (collections.Length > 0)
                    currentEnumerator = collections[0].GetEnumerator();
                else
                    return false;
            }
            while (!currentEnumerator.MoveNext())
            {
                currentEnumerator.Dispose();
                currentEnumerator = null;

                currentIndex++;
                if (currentIndex >= collections.Length)
                    return false;
                currentEnumerator = collections[currentIndex].GetEnumerator();
            }
            return true;
        }

        public void Reset()
        {
            if (currentEnumerator != null)
            {
                currentEnumerator.Dispose();
                currentEnumerator = null;
            }
            this.currentIndex = -1;
        }
    }

}

Try the SelectMany extension method added in 3.5. 尝试在3.5中添加的SelectMany扩展方法。

IEnumerable<IEnumerable<int>> e = ...;
foreach ( int cur in e.SelectMany(x => x)) {
  Console.WriteLine(cur);
}

The code SelectMany(x => x) has the effect of flattening a collection of collections into a single collection. 代码SelectMany(x => x)具有将集合集合展平为单个集合的效果。 This is done in a lazy fashion and allows for straight forward processing as shown above. 这是以懒惰的方式完成的,并允许如上所示的直接处理。

If you only have C# 2.0 available, you can use an iterator to achieve the same results. 如果只有C#2.0可用,则可以使用迭代器来获得相同的结果。

public static IEnumerable<T> Flatten<T>(IEnumerable<IEnumerable<T>> enumerable) {
  foreach ( var inner in enumerable ) {
    foreach ( var value in inner ) {
      yield return value;
    }
  }
}

Just use the Enumerable.Concat() extension method to "concatenate" two IEnumerables. 只需使用Enumerable.Concat()扩展方法来“连接”两个IEnumerables。 Don't worry, it doesn't actually copy them into a single array (as you might infer from the name), it simply allows you to enumerate over them all as if they were one IEnumerable. 不用担心,它实际上并没有将它们复制到一个数组中(正如您可能从名称中推断出来的那样),它只是允许您枚举它们,就像它们是IEnumerable一样。

If you have more than two then Enumerable.SelectMany() would be better. 如果你有两个以上,那么Enumerable.SelectMany()会更好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 .NET 是否有内置的 EventArgs<T> ? - Does .NET have a built-in EventArgs<T>? 错误:清单 <int> 没有匹配的&#39;System.Collections.Generic.IEnumerable <int> - Error: List<int> does not have the matching of 'System.Collections.Generic.IEnumerable<int> dot net是否有像IEnumerable这样的接口和Count属性? - Does dot net have an interface like IEnumerable with a Count property? IEnumerable,List或??? 用于返回ADO.NET集合? - IEnumerable, List, or ??? for returning ADO.NET collections? 内置.NET延迟执行的IEnumerable类? - Built in .Net IEnumerable class that defers execution? C#/。NET是否具有内置的“ VersionNumber”类? - Does C#/.NET have a built-in “VersionNumber” class? .NET框架是否内置有任何附加的属性或附加的行为? - Does the .NET framework have any attached properties or attached behaviors built into it? 为什么.NET中的这么多命名集合没有实现IEnumerable <T> ? - Why do so many named collections in .NET not implement IEnumerable<T>? LINQ to Entities无法识别方法&#39;System.Collections.Generic.IEnumerable`1 - LINQ to Entities does not recognize the method 'System.Collections.Generic.IEnumerable`1 “System.Collections.Generic.IEnumerable <short> &#39;不包含&#39;Sum&#39;的定义 - 'System.Collections.Generic.IEnumerable<short>' does not contain a definition for 'Sum'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM