2012-03-09 1 views
3

Мне нужно передать переменную типа IDictionary<Guid, IEnumerable<Guid>> в метод. Когда я использую следующий код:Использование Linq для объектов, метод ToDictionary, не удовлетворяющий требованиям типа

var userGroupDictionary = _selectedUsers.ToDictionary(u => u.UserGuid, u => u.GroupUsers.Select(gu => gu.Group.GroupGuid).ToList()); 

Я получаю следующее сообщение об ошибке:

cannot convert from System.Collections.Generic.Dictionary<System.Guid,System.Collections.Generic.List<System.Guid>>' to 'System.Collections.Generic.IDictionary<System.Guid,System.Collections.Generic.IEnumerable<System.Guid>>' 

Когда я перебирать свою коллекцию он работает, однако:

var userGroupDictionary = new Dictionary<Guid, IEnumerable<Guid>>(); 
foreach (var user in _selectedUsers.Where(user => !userGroupDictionary.ContainsKey(user.UserGuid))) 
{ 
    userGroupDictionary.Add(user.UserGuid, user.GroupUsers.Select(gu => gu.Group.GroupGuid).ToList()); 
} 

Любые идеи, что происходит? Является ли компилятор не может сказать, что Dictionary<Guid, List<Guid>> удовлетворяет IDictionary<Guid, IEnumerable<Guid>>

ответ

1

Проблемы заключается в том, что умозаключение типа возвращает Dictionary<Guid, List<Guid>>, который является неправильным типом для метода вы хотите позвонить. Это немного больше, чем это, но это связано с обсуждением дисперсии типов. Вы можете решить проблему с расширением AsEnumerable:

var userGroupDictionary = _selectedUsers 
    .ToDictionary(
     u => u.UserGuid, 
     u => u.GroupUsers.Select(gu => gu.Group.GroupGuid).ToList().AsEnumerable()); 

... или вы можете сделать простой бросок, как в следующем примере:

var userGroupDictionary = _selectedUsers 
    .ToDictionary(
     u => u.UserGuid, 
     u => (IEnumerable<Guid>)u.GroupUsers.Select(gu => gu.Group.GroupGuid).ToList()); 

Если вы просто опустить ToList(), как рекомендуют другие , вывод типа действительно отобразит тип, который вы ожидаете, но возвращенный IEnumerable будет иметь отсроченное выполнение, которое может быть или не быть проблемой для вас. Оставляя ToList, но делая подборки, вы сразу же оцениваете элементы, а не лениво оцениваете их во время итерации.

Более подробной информации о отсроченном исполнении, см «лени» (думают, ленивые оценки) раздел Jon Skeet's Edulinq series, part 44

+0

Да, у меня возникали проблемы с отложенным исполнением. После оценки я бы не подумал об AsEnumerable. Я хотел бы узнать больше о проблеме дисперсии типа, хотя и, скорее всего, поставит другой вопрос. Ваш ответ отлично работает для меня, благодарю вас! –

1

линия ниже создает словарь, где ключ типа Guid и значение типа List<Guid>.

_selectedUsers.ToDictionary(
        u => u.UserGuid, 
        u => u.GroupUsers.Select(gu => gu.Group.GroupGuid).ToList() 
        ); 

Так просто удалить .ToList() и это все, u.GroupUsers.Select() сама возвращает IEnumerable<Guid>.

И вы в состоянии итерация на обоих значений, так как List implementes IEnumerable а, это прийти, чтобы удовлетворить foreach итератор.

+0

Параметр '.ToList()' имеет эффект перечисляя 'u.GroupUsers' сразу, что может или не может иметь значение. Это будет иметь значение, если 'u.GroupUsers', например, получает результаты из базы данных. – hvd

0

Is the compiler unable to tell that Dictionary<Guid, List<Guid>> satisfies IDictionary<Guid, IEnumerable<Guid>>

Нет, компилятор может сказать, что Dictionary<Guid, List<Guid>>не удовлетворяют IDictionary<Guid, IEnumerable<Guid>>. Последнее обеспечивает, например, метод Add(Guid, IEnumerable<Guid>), который ваш словарь не может поддерживать.

Вы можете явно указать допустимые значения в словаре, например, с помощью

_selectedUsers.ToDictionary<User, Guid, IEnumerable<Guid>>(
    u => u.UserGuid, 
    u => u.GroupUsers.Select(gu => gu.Group.GroupGuid).ToList()) 
0

Я думаю, что все u.GroupUsers имеет Same идентификатор_группы. Вы можете получить первый идентификатор groupID, Если вы можете получить доступ к свойству groupID в классе пользователя. Вы должны использовать GroupID. Как _selectedUsers.ToDictionary(u=>u.UserGuid,u.GroupID); Если вы не можете получить доступ к GroupId в классе пользователей. Использование:

_selectedUsers.ToDictionary(
        u => u.UserGuid, 
        u => u.GroupUsers.Select(gu => gu.Group.GroupGuid).First()); 
+0

Почему у них такой же идентификатор группы? Вопрос подсказывает мне, что пользователь может быть членом нескольких групп. – hvd

+0

Сценарий. Я думал. Существует ассоциация User to Group on GroupID. – halit

 Смежные вопросы

  • Нет связанных вопросов^_^