2010-11-22 9 views
6

Учитывая следующий код, у меня возникают проблемы с возвратом Словаря.ToDictionary не работает должным образом

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

я получаю следующие ошибки ..

«System.Collections.Generic.IDictionary» не содержит определение для «ToDictionary» и лучшей перегрузки методы расширения «System.Linq.Enumerable .ToDictionary (System.Collections.Generic.IEnumerable, System.Func, System.Collections.Generic.IEqualityComparer)»имеет некоторые недопустимые аргументы

не может преобразовать из 'лямбда-выражения' до 'System.Func'

не может преобразовать из 'лямбда выражения' в 'System.Collections.Generic.IEqualityComparer

В классе продукта нет ничего особенного. она просто определяется как

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

@Brad Christie: `IDictionary `реализует` IEnumerable > `и существует метод расширения` IEnumerable >. ToDictionary`, определенный в статическом классе `Enumerable`. – jason 2010-11-22 15:54:31

ответ

10

Почему вы используете

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

вместо просто

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

?


Это потому, что

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

Посмотрите на номер (3) и типы параметров универсального типа (Func).

, что означает, что вы должны назвать его:

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

Нет перегрузки для метода 'ToDictionary' принимает 0 аргументов – Ciel 2010-11-22 15:53:08

1

Не указывайте параметры универсального типа в явном виде. Типы в ToDictionary<T1, T2> не являются T1 = TKey и T2 = TValue (где TKey - это тип ключа результирующего словаря, а TValue - тип результирующего значения в словаре).

Перегрузка ToDictionary, которая принимает два типовых типа, имеет T = TSource и V = TKey. Здесь TSource = KeyValuePair<Product, int>. Кроме того, вы вызываете overload of ToDictionary, который имеет два параметра. Первым параметром является карта от T1 -> T2, а вторая - IEqualityComparer<T2>. Но x => x.Key не карта от KeyValuePair<Product, int> до int и v => v.Value не является IEqualityComparer<int>.

Если вы не зададите параметры универсального типа явно, компилятор проверяет типы x => x.Key и v => v.Value и смотрит на различных перегрузках ToDictionary.Есть четыре

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

Обратите внимание, что он может немедленно исключить из 1. и 4. потому что они имеют неверное число параметров (2 и 4 соответственно, тогда как вы вызываете перегрузку, которая требует трех параметров (третий - это скрытый первый параметр, потому что вы вызываете extensi сверху метод)). Это может исключить 2. поскольку последний параметр не может быть преобразован в IEqualityComparer<T> для любого T. Это оставляет последнюю перегрузку. Он способен сделать вывод, что x => x.Key является Func<KeyValuePair<Product, int>, Product>, что v => v.Value является Func<KeyValuePair<Product, int>, int> и потому, что вы вызываете

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

Если вы хотите, чтобы указать параметры типа явно вы должны сказать

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

Если вы на самом деле не клонируете экземпляры продукта, вы можете просто:

public virtual IDictionary<Product, int> JsonProducts 
{ 
    get 
    { 
     return new Dictionary(Products); 
    } 
} 
Смежные вопросы