2010-11-22 37 views
6

Dado el siguiente código, tengo problemas para devolver un diccionario.ToDictionary no funciona como se esperaba

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

que obtienen los siguientes errores ..

'System.Collections.Generic.IDictionary' no contiene una definición para 'ToDictionary' y el mejor método de extensión de sobrecarga 'System.Linq.Enumerable .ToDictionary (System.Collections.Generic.IEnumerable, System.Func, System.Collections.Generic.IEqualityComparer)' tiene algunos argumentos no válidos

no puede convertir de 'expresión lambda' a 'System.Func'

no se puede convertir de 'expresión lambda' a 'System.Collections.Generic.IEqualityComparer

No hay nada especial acerca de la clase Product. que se define simplemente como

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

@Brad Christie: 'IDictionary 'implementa' IEnumerable > 'y hay un método de extensión' IEnumerable >. ToDictionary' definido en la clase estática 'Enumerable'. – jason

Respuesta

10

¿Por qué usan

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

en lugar de sólo

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

?


Eso es porque

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

echar un vistazo para el número (3) y los tipos de parámetros de tipo genérico (Func).

que significa que se necesita para llamarlo:

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

Sin sobrecarga para el método 'ToDictionary' toma 0 argumentos – Ciel

+0

@Stacey: ¡Por supuesto! Ver mi publicación editada .. – abatishchev

+1

¿Por qué convertir un diccionario a un diccionario? ¿No debería devolver "Productos" lo mismo que OriginalType.ToOriginalType? –

1

No especifique los parámetros de tipo genérico de forma explícita. Los tipos en ToDictionary<T1, T2> no son T1 = TKey y T2 = TValue (donde TKey es el tipo de la clave del diccionario resultante y TValue es el tipo del valor resultante en el diccionario).

La sobrecarga de ToDictionary que acepta dos parámetros genéricos de tipo tiene T = TSource y V = TKey. Aquí, TSource = KeyValuePair<Product, int>. Además, está invocando el overload of ToDictionary que tiene dos parámetros. El primer parámetro es un mapa de T1 -> T2 y el segundo es un IEqualityComparer<T2>. Pero x => x.Key no es un mapa de KeyValuePair<Product, int> a int y v => v.Value no es un IEqualityComparer<int>.

Cuando no se especifica los parámetros de tipo genérico de forma explícita, el compilador inspecciona los tipos de x => x.Key y v => v.Value y mira a las diversas sobrecargas de ToDictionary.Hay cuatro

  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>)

Tenga en cuenta que se puede descartar inmediatamente y 1. 4. porque tienen un número incorrecto de parámetros (2 y 4 respectivamente mientras está invocando una sobrecarga que necesita tres parámetros (el tercero es el primer parámetro oculto porque está invocando una extensión en el método)). Puede descartar 2. porque el último parámetro no se puede convertir a IEqualityComparer<T> para cualquier T. Esto deja la última sobrecarga. Es capaz de deducir que x => x.Key es una Func<KeyValuePair<Product, int>, Product>, que v => v.Value es una Func<KeyValuePair<Product, int>, int> y por lo tanto que está invocando

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

Si desea especificar los parámetros de tipo de forma explícita que tendría que decir

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

Si no está clonando las instancias del Producto, puede hacerlo:

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