Given the following code, I am having trouble returning a Dictionary.
[JsonProperty]
public virtual IDictionary<Product, int> JsonProducts
{
get
{
return Products.ToDictionary<Product, int>(x => x.Key, v => v.Value);
}
}
public virtual IDictionary<Product, int> Products { get; set; }
I get the following errors..
'System.Collections.Generic.IDictionary' does not contain a definition for 'ToDictionary' and the best extension method overload 'System.Linq.Enumerable.ToDictionary(System.Collections.Generic.IEnumerable, System.Func, System.Collections.Generic.IEqualityComparer)' has some invalid arguments
cannot convert from 'lambda expression' to 'System.Func'
cannot convert from 'lambda expression' to 'System.Collections.Generic.IEqualityComparer
There is nothing special about the Product class. it is simply defined as
class Product
{
public virtual int Id { get; set; }
public virtual String Name { get; set; }
}
Why do you use
Products.ToDictionary<Product, int>(x => x.Key, v => v.Value)
instead of just
Products.ToDictionary(x => x.Key, v => v.Value)
?
That's because
public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector
);
Take a look to the number (3) and types of generic type parameters (Func).
which means that you need to call it:
Products.ToDictionary<KeyValuePair<Product, int>, Product, int>(x => x.Key, v => v.Value);
Don't specify the generic type parameters explicitly. The types in ToDictionary<T1, T2>
are not T1 = TKey
and T2 = TValue
(where TKey
is the type of the key of the resulting dictionary and TValue
is the type of the resulting value in the dictionary).
The overload of ToDictionary
that accepts two generic type parameters has T = TSource
and V = TKey
. Here, TSource = KeyValuePair<Product, int>
. Further, you are invoking the overload of ToDictionary
that has two parameters. The first parameter is a map from T1 -> T2
and the second is an IEqualityComparer<T2>
. But x => x.Key
is not a map from KeyValuePair<Product, int>
to int
and v => v.Value
is not an IEqualityComparer<int>
.
When you don't specify the generic type parameters explicitly, the compiler inspects the types of x => x.Key
and v => v.Value
and looks at the various overloads of ToDictionary
. There are four
ToDictionary<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>)
ToDictionary<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>, IEqualityComparer<TKey>)
ToDictionary<TSource, TKey, TElement>(IEnumerable<TSource>, Func<TSource, TKey>, Func<TSource, TElement>)
ToDictionary<TSource, TKey, TElement>(IEnumerable<TSource>, Func<TSource, TKey>, Func<TSource, TElement>, IEqualityComparer<TKey>)
Note that it can immediately rule out 1. and 4. because they have the wrong number of parameters (2 and 4 respectively whereas you are invoking an overload that needs three parameters (the third is the hidden first parameter because you are invoking an extension method)). It can rule out 2. because the last parameter can not be converted to an IEqualityComparer<T>
for any T
. This leaves the last overload. It is able to deduce that x => x.Key
is a Func<KeyValuePair<Product, int>, Product>
, that v => v.Value
is a Func<KeyValuePair<Product, int>, int>
and therefore that you are invoking
ToDictionary<KeyValuePair<Product, int>, Product, int>(
IEnumerable<KeyValuePair<Product, int>>,
Func<KeyValuePair<Product, int>, Product>,
Func<KeyValuePair<Product, int>, int>
)
If you wanted to specify the type parameters explicitly you would have to say
Products.ToDictionary<KeyValuePair<Product, int>, Product, int>(
x => x.Key,
v => v.Value
);
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