I have an ILookup<int, Derived>
and I want to return an ILookup<int, Base>
where Derived
implements or extends Base
.
Currently I use SelectMany()
and then ToLookup()
to first extract the key value pairs of ILookup<int, Derived>
into a flat IEnumerable
and then create a new ILookup<int, Base>
:
class Base { }
class Derived: Base { }
class Test
{
ILookup<int, Base> CastLookup(ILookup<int, Derived> existing)
{
IEnumerable<KeyValuePair<int, Base>> flattened = existing.SelectMany(
(x) => x,
(gr, v) => new KeyValuePair<int, Base>(gr.Key, (Base)v)); // I know the explicit cast can be implicit here; it is just to demonstrate where the up casting is happening.
ILookup<int, Base> result = flattened.ToLookup(
(x) => x.Key,
(x) => x.Value);
return result;
}
}
How can I convert an ILookup without iterating its entries and then repacking them?
NOTE: A related question is Shouldn't ILookup<TKey, TElement> be (declared) covariant in TElement? by bigge. Ryszard Dżegan answers that it is mostly for historical reasons: ILookup<TKey, TElement>
has been developed before generics with covariance.
Herzmeister asks something similar for a Dictionary<TKey, TValue>
. Mehrdad Afshari answers that for the mutable dictionary the covariance would not be safe.
Indeed, if Ilookup<TKey, TElement>
was covariant in TElement
, I would not have run into this instance of the ILookup<TKey, TElement>
casting question; but it is not, so my quest for a better way still continues.
NOTE: I can of course write an extension method to do it, but that does not prevent the required computational work of iterating and repacking.