How to create a collection based on several IEnumerables

The class I want to work with provides getters of type IEnumerable<X>and IEnumerable<Y>, where X and Y are subclasses of the base type T. I want to iterate over the contents of both the type in question and the type T. Is there a convenient way to combine both into something that 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 third line does not work:

'System.Collections.Generic.IEnumerable' does not contain a definition for 'Concat' and the best extension method is 'System.Linq.Enumerable.Concat (System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerable)' has some invalid the arguments

Notice, I can’t change any of the source data, I need to create a new collection - in fact I want to make foreachit over it.

+3
source share
4 answers

You can use the Cast function to convert IEnumerable<X>to IEnumerable<T>, and then Concatto add a second series

Sort of:

listB.Cast<A>().Concat(listC.Cast<A>())
+6
source

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

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

In your specific case, you can use List.AddRange:

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

We did not test and did not know about the ready-made functions for it, but instead of highlighting new data about storage and movement, you should implement your own template template EnumeratorBinder<T, X, Y>linking two instances IEnumerablein the constructor and implement something in the lines

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

with suitable template restrictions ...

+1
source

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
source

Source: https://habr.com/ru/post/1756164/


All Articles