I'm trying to write an extension method that will convert IDictionary<K, S<V>>
holding any type of collection/sequence (S<V>
) to ILookup<K, V>
which is more proper data structure in those cases. This means I'd like my extension to work on different S
types and interfaces:
IDictionary<K, IEnumerable<V>>
IDictionary<K, ICollection<V>>
IDictionary<K, List<V>>
etc. Ideally, I don't want to write separate implementation for each possible collection type AND I want type inference to do its job.
What I've tried is:
public static ILookup<TKey, TValue>ToLookup<TKey, TCollection, TValue>(
this IDictionary<TKey, TCollection> dictionary)
where TCollection : IEnumerable<TValue>
But it have no TValue
in parameters list, so type inference is unable to figure it out - I get "The type arguments for method ToLookup cannot be inferred from the usage".
Is there a chance it could work somehow in other way than adding fake TValue
-typed parameter to the method?
Examples of expected usage
I hope all above calls to be possible and result in a call to my single extension method:
var dictOfIEnumerables = new Dictionary<int, IEnumerable<int>>();
var lookupFromIEnumerables = dictOfIEnumerables.ToLookup();
var dictOfICollections = new Dictionary<int, ICollection<int>>();
var lookupFromICollections = dictOfICollections.ToLookup();
var dictOfLists = new Dictionary<int, List<int>>();
var lookupFromLists = dictOfLists.ToLookup();
Because all collections implement IEnumerable<T>
, we can just use it instead of the TCollection
type paramter. Unfortunately the type inference does not know this. This is the code I wrote:
public static ILookup<TKey, TValue> ToLookup<TKey, TValue>
(this IDictionary<TKey, IEnumerable<TValue>> dict)
{
return dict.SelectMany(p => p.Value.Select
(v => new KeyValuePair<TKey, TValue>(p.Key, v)))
.ToLookup(p => p.Key, p => p.Value);
}
There seems to be no way of making the type inference work, but this method will work if you cast the Dictionary:
((IDictionary<int, IEnumerable<int>>)dictOfLists).ToLookup()
Also you can add Lists to a Dictionary of IEnumerables and cast them back when you need them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With