开发者

How can you create a collection based on multiple IEnumerables

A class I want to operate on provides getters of type IEnumerable<X> and IEnumerable<Y> where X & Y are subclasses of base type T. I want to iterate over the contents of both treating them as type T. Is there a handy way to concatenate both into something which can be seen as IEnumerable<T>?

Example:

        IEnumerable<HeaderPart> headers = templateFile.MainDocumentPart.HeaderParts;
        IEnumerable<FooterPart> footers = templateFile.MainDocumentPart.FooterParts;
        List<OpenXmlPart> result = new List<OpenXmlPart>();
        result.Concat<OpenXmlPart>(footers);

HeaderPart and FooterPart are both subclasses of OpenXmlPart but the 3rd line fails:

'System.Collections.Generic.IEnumerable' does not contain a definition for 'Concat' and the best extension method overload 'System.Linq.Enumerable.Concat(System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerable)' has some inval开发者_StackOverflow中文版id arguments

Note, I can't change either of the source data, I need to create a new collection - actually I want to do a foreach over it.


You can use the Cast function to convert IEnumerable<X> to IEnumerable<T> and then Concat to append the second series

Something like:

listB.Cast<A>().Concat(listC.Cast<A>())


In C#/.NET 4 or newer you can use Enumerable.Concat<T>:

IEnumerable<T> result = xs.Concat<T>(ys);

For your specific case you can use List.AddRange:

List<OpenXmlPart> result = new List<OpenXmlPart>();
result.AddRange(headers.Cast<OpenXmlPart>());
result.AddRange(footers.Cast<OpenXmlPart>());


Haven't tested, and don't know about readymade functionality for it, but instead of allocating new storage and moving data about, you should be able implement your own EnumeratorBinder<T, X, Y> template class, binding the two IEnumerable instances in the constructor, and implement something on the lines of

IEnumerable<T> GetEnumerable()
{
  foreach ( X x in _enumX )
    yield return x;
  foreach ( Y y in _enumY )
    yield return y;
}

with suitable template constraints...


If you are sure your IEnumerable is a list you can use AddRange()

IEnumerable<int> list1 = new List<int>() { 1, 2, 3 };
IEnumerable<int> list2 = new List<int>() { 4, 5, 6 };
((List<int>)list1).AddRange(list2);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜