使用Linq到对象,ToDictionary方法不满足类型要求

本文关键字:不满足 类型 方法 ToDictionary Linq 对象 使用 | 更新日期: 2023-09-27 18:27:22

我需要将类型IDictionary<Guid, IEnumerable<Guid>>的变量传递到方法中。 当我使用以下代码时:

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

使用Linq到对象,ToDictionary方法不满足类型要求

问题是类型推断返回了一个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 的 Edulinq 系列的第 44 部分的"懒惰"(想想懒惰计算(部分

下面的行创建一个字典,其中 Guid 类型的键和 List<Guid> 类型的值。

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

因此,只需删除.ToList()即可,u.GroupUsers.Select()本身返回IEnumerable<Guid>.

而且您可以迭代这两个值,因为List也实现了IEnumerable,这足以满足foreach迭代器。

编译器是否无法判断Dictionary<Guid, List<Guid>>满足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())

我想你们所有人都有相同的组ID。你可以得到第一个组ID,如果可以访问用户类上的组 ID 属性。您应该使用组 ID。喜欢_selectedUsers.ToDictionary(u=>u.UserGuid,u.GroupID);如果无法访问用户类上的组 ID。用:

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