使用List<T>.Except方法时类型转换无效的问题求助
我创建了User和UserComparison两个简单类:User类仅包含UserId、UserName以及List<string> UserGroups;UserComparison类包含两个User实例成员,以及两个用于对比UserGroups的属性。
原本想用Except方法返回两组用户组的差集,对应属性代码如下:
public List<string> DifferenceSetAtoB { get { return (List<string>)UserA.UserGroups.Except((List<string>)UserB.UserGroups); } }
但运行时触发了以下错误:
System.InvalidCastException
HResult=0x80004002
Message=Unable to cast object of type 'd__811[System.String]' to type 'System.Collections.Generic.List1[System.String]'.
我以为UserB.UserGroups是List<string>类型,Except作为集合方法返回的也应该是List<string>,但不知道怎么让类型一致。List不就属于System.Collections.Generic吗?
完整代码如下:
public class User { public string UserId { get; set; } public string UserName { get; set; } public List<string> UserGroups { get; set; } public User() { this.UserGroups = new List<string>(); } } public class UserComparison { public User UserA { get; set; } public User UserB { get; set; } public List<string> DifferenceSetAtoB { get { return (List<string>)UserA.UserGroups.Except((List<string>)UserB.UserGroups); } } public List<string> DifferenceSetBtoA { get { return (List<string>)UserB.UserGroups.Except((List<string>)UserA.UserGroups); } } public UserComparison() { this.UserA = new User(); this.UserB = new User(); } }
问题根源
Enumerable.Except方法的返回类型是IEnumerable<T>,不是List<T>。你看到的d__811[System.String]是LINQ延迟执行生成的内部枚举器类型,它实现了IEnumerable,但**不能直接强制转换为List**——哪怕两者同属System.Collections.Generic`命名空间,类型层级也不允许这种转换。
另外,代码里对UserB.UserGroups的(List<string>)强制转换完全多余,因为UserGroups本身就是List<string>类型,直接传入即可。
修正后的代码
只需要给Except的返回结果调用ToList()方法,就能将IEnumerable<string>转换为List<string>:
public class UserComparison { public User UserA { get; set; } public User UserB { get; set; } public List<string> DifferenceSetAtoB { get { return UserA.UserGroups.Except(UserB.UserGroups).ToList(); } } public List<string> DifferenceSetBtoA { get { return UserB.UserGroups.Except(UserA.UserGroups).ToList(); } } public UserComparison() { this.UserA = new User(); this.UserB = new User(); } }
补充说明
- 大部分LINQ方法(如
Except、Where、Select)默认返回IEnumerable<T>,采用延迟执行逻辑——只有当你遍历结果,或者调用ToList()/ToArray()这类方法时,才会真正执行查询并生成具体的集合实例。 - 如果需要返回
List<T>,必须显式调用ToList(),而不是用强制类型转换。
内容的提问来源于stack exchange,提问作者wkSpeaker

