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);
精彩评论