2010-11-22 5 views
6

Étant donné le code suivant, j'ai du mal à renvoyer un dictionnaire.ToDictionary ne fonctionne pas comme prévu

[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; } 

Je reçois les erreurs suivantes ..

'System.Collections.Generic.IDictionary' ne contient pas une définition pour 'ToDictionary' et la meilleure surcharge de méthode d'extension « System.Linq.Enumerable .ToDictionary (System.Collections.Generic.IEnumerable, System.Func, System.Collections.Generic.IEqualityComparer) » a des arguments invalides

ne convertit pas 'expression lambda' à 'System.Func'

ne peut pas convertir de 'expression lambda' en 'System.Collections.Generic.IEqualityComparer

Il n'y a rien de spécial à propos de la classe de produit. il est simplement défini comme

class Product 
{ 
    public virtual int Id { get; set; } 
    public virtual String Name { get; set; } 
} 
+0

@Brad Christie: 'IDictionary 'implements' IEnumerable > 'et il existe une méthode d'extension' IEnumerable >. ToDictionary' défini dans la classe statique 'Enumerable'. – jason

Répondre

10

Pourquoi utilisez-vous

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

au lieu de simplement

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

?


C'est parce que

public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
    this IEnumerable<TSource> source, 
    Func<TSource, TKey> keySelector, 
    Func<TSource, TElement> elementSelector 
); 

Jetez un oeil au nombre (3) et les types de paramètres de type générique (Func).

ce qui signifie que vous devez appeler:

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

Aucune surcharge pour la méthode 'ToDictionary' prend 0 argument – Ciel

+0

@Stacey: Bien sûr! Voir mon post édité .. – abatishchev

+1

Pourquoi voudriez-vous convertir un dictionnaire en dictionnaire? Ne devrait-il pas retourner les "Produits" identiques à OriginalType.ToOriginalType? –

1

Ne pas préciser les paramètres explicitement de type générique. Les types dans ToDictionary<T1, T2> ne sont pas T1 = TKey et T2 = TValue (où TKey est le type de la clé du dictionnaire résultant et TValue est le type de la valeur résultante dans le dictionnaire). La surcharge de ToDictionary qui accepte deux paramètres de type générique a T = TSource et V = TKey. Ici, TSource = KeyValuePair<Product, int>. En outre, vous appelez le overload of ToDictionary qui a deux paramètres. Le premier paramètre est une carte de T1 -> T2 et le second est un IEqualityComparer<T2>. Mais x => x.Key n'est pas une carte de KeyValuePair<Product, int> à int et v => v.Value n'est pas un IEqualityComparer<int>.

Lorsque vous ne spécifiez pas explicitement les paramètres de type générique, le compilateur inspecte les types x => x.Key et v => v.Value et examine les différentes surcharges de ToDictionary.Il y a quatre

  1. ToDictionary<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>)
  2. ToDictionary<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>, IEqualityComparer<TKey>)
  3. ToDictionary<TSource, TKey, TElement>(IEnumerable<TSource>, Func<TSource, TKey>, Func<TSource, TElement>)
  4. ToDictionary<TSource, TKey, TElement>(IEnumerable<TSource>, Func<TSource, TKey>, Func<TSource, TElement>, IEqualityComparer<TKey>)

Notez qu'il peut immédiatement exclure 1. et 4. parce qu'ils ont le nombre de paramètres (2 et 4 respectivement alors que vous invoquez une surcharge qui a besoin de trois paramètres (le troisième est le premier paramètre caché parce que vous invoquez un extensi sur la méthode)). Il peut exclure 2. parce que le dernier paramètre ne peut pas être converti en IEqualityComparer<T> pour T. Cela laisse la dernière surcharge. Il est capable de déduire que x => x.Key est un Func<KeyValuePair<Product, int>, Product>, que v => v.Value est un Func<KeyValuePair<Product, int>, int> et donc que vous invoquez

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

Si vous vouliez spécifier explicitement les paramètres de type que vous auriez à dire

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

Si vous ne clonez pas les instances Product, vous pouvez simplement:

public virtual IDictionary<Product, int> JsonProducts 
{ 
    get 
    { 
     return new Dictionary(Products); 
    } 
} 
Questions connexes