Компилятор не может определить тип из обернутого generi c IEnumerable - PullRequest
1 голос
/ 01 апреля 2020

Я пытаюсь написать обобщенный c метод расширения для словаря типа Dictionary<TKey, IEnumerable<TValue>>, который должен возвращать экземпляр IEnumerable<TValue> для данного ключа, и если для этого ключа еще нет записи, создайте новый экземпляр IEnumerable<TValue> и добавьте его для этого ключа.

public static TEnumerable GetAndEnsureEnumerableForKey<TKey, TValue, TEnumerable>(
  this Dictionary<TKey, TEnumerable> dictionary, TKey key)
    where TEnumerable : IEnumerable<TValue> 
{
  TEnumerable enumerableForKey;
  if (!dictionary.TryGetValue(key, out enumerableForKey)) 
  {
    Type enumerableType = typeof(TEnumerable);
    enumerableForKey = (TEnumerable)Activator.CreateInstance(enumerableType);
    dictionary.Add(key, enumerableForKey);
  }

  return enumerableForKey;
}

Сам метод работает нормально, но у меня проблема с вызовом этого метода. Учитывая Dictionary<int, List<int>> intListDictionary, я бы ожидал, что вызов intListDictionary.GetAndEnsureEnumerableForKey(sampleInt); будет работать нормально. Однако компилятор жалуется, что он не может вывести тип TValue из вызова метода, и мне нужно было бы вызвать intListDictionary.GetAndEnsureEnumerableForKey<int, int, List<int>>(sampleInt);, что побеждает назначение обобщений для этого случая.

Как это получается, что компилятор не может вывести тип TValue, когда TEnumerable является ограничением на IEnumerable<TValue>, и конкретный словарь, из которого я вызываю, должен знать тип?

1 Ответ

2 голосов
/ 01 апреля 2020

Выводы типа делаются только на основе аргументов типа, а не ограничений типа, как объяснено в этом ответе .

Чтобы достичь того, что вы хотите, вы можете изменить ограничение типа для TEnumerable к не универсальному c IEnumerable интерфейсу:

public static TEnumerable GetAndEnsureEnumerableForKey<TKey, TEnumerable>(
    this Dictionary<TKey, TEnumerable> dictionary,
    TKey key)
    where TEnumerable : IEnumerable
{
    TEnumerable enumerableForKey;
    if (!dictionary.TryGetValue(key, out enumerableForKey))
    {
        Type enumerableType = typeof(TEnumerable);
        enumerableForKey = (TEnumerable)Activator.CreateInstance(enumerableType);
        dictionary.Add(key, enumerableForKey);
    }

    return enumerableForKey;
}

Вам необходимо добавить System.Collections, чтобы сделать интерфейс IEnumerable доступным.

...