ToDictionary is not working properly

Given the following code, I am having problems returning the 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 method for overloading the add-in is 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 the expression '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; } } 
+6
c # linq
source share
3 answers

Why are you using

 Products.ToDictionary<Product, int>(x => x.Key, v => v.Value) 

instead

 Products.ToDictionary(x => x.Key, v => v.Value) 

?


It'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 at the number (3) and parameter types of type type (Func).

which means you need to call it:

 Products.ToDictionary<KeyValuePair<Product, int>, Product, int>(x => x.Key, v => v.Value); 
+10
source share

Do not specify type parameters explicitly. The types ToDictionary<T1, T2> are not T1 = TKey and T2 = TValue (where TKey is the key type of the resulting dictionary, and TValue is the type of the resulting value in the dictionary).

The ToDictionary overload, which takes two typical types, has T = TSource and V = TKey . Here TSource = KeyValuePair<Product, int> . In addition, you call the ToDictionary overload , which has two parameters. The first parameter is a map from T1 -> T2 , and the second is IEqualityComparer<T2> . But x => x.Key not a mapping from KeyValuePair<Product, int> to int , and v => v.Value not IEqualityComparer<int> .

Unless you specify parameters of a typical type explicitly, the compiler checks the types x => x.Key and v => v.Value and looks at various ToDictionary overloads. 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 exclude 1 and 4. since they have the wrong number of parameters (2 and 4, respectively, while you are causing an overload that requires three parameters (the third is the hidden first parameter because you are calling the extension method)) . It can exclude 2. since the last parameter cannot be converted to IEqualityComparer<T> for any T This leaves the last overload. It can deduce that x => x.Key is Func<KeyValuePair<Product, int>, Product> , that v => v.Value is Func<KeyValuePair<Product, int>, int> and therefore you call

 ToDictionary<KeyValuePair<Product, int>, Product, int>( IEnumerable<KeyValuePair<Product, int>>, Func<KeyValuePair<Product, int>, Product>, Func<KeyValuePair<Product, int>, int> ) 

If you want to explicitly specify type parameters, you must say

 Products.ToDictionary<KeyValuePair<Product, int>, Product, int>( x => x.Key, v => v.Value ); 
+1
source share

If you are not actually cloning product instances, you can simply do:

 public virtual IDictionary<Product, int> JsonProducts { get { return new Dictionary(Products); } } 
0
source share

All Articles