是否可以将Except()
用于两个具有两个不同类但具有公共字段的List?我有List<User1>
和List<User2>
个收藏集。它们具有除Id列以外的不同属性,我想使用此Id列找到它们之间的不同记录。我正在尝试使用List<>.Except()
但我收到此错误:
无法从用法推断出方法'System.Linq.Enumerable.Except(System.Collections.Generic.IEnumerable,System.Collections.Generic.IEnumerable)'的类型参数。尝试明确指定类型参数。
以下是我正在尝试的内容:
List<User1> list1 = List1();
List<User2> list2 = List2();
var listdiff = list1.Except(list2.Select(row => row.Id));
我做错了什么?
答案 0 :(得分:9)
List1包含User1的实例,List2包含User2的实例。
list1.Except(list2.Select(row => row.Id))
应该生成什么类型的实例?
换句话说,如果类型推断不可用,您会用{<1}}替换什么?
如果User1和User2继承自相同的祖先(带有ID),请改用var
。
否则:
List<User>
答案 1 :(得分:4)
不是Except
,但是正确的结果和类似的表现:
// assumes that the Id property is an Int32
var tempKeys = new HashSet<int>(list2.Select(x => x.Id));
var listdiff = list1.Where(x => tempKeys.Add(x.Id));
当然,您可以将它全部包装在您自己的可重复使用的扩展方法中:
var listdiff = list1.Except(list2, x => x.Id, y => y.Id);
// ...
public static class EnumerableExtensions
{
public static IEnumerable<TFirst> Except<TFirst, TSecond, TKey>(
this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst, TKey> firstKeySelector,
Func<TSecond, TKey> secondKeySelector)
{
// argument null checking etc omitted for brevity
var keys = new HashSet<TKey>(second.Select(secondKeySelector));
return first.Where(x => keys.Add(firstKeySelector(x)));
}
}
答案 2 :(得分:3)
简而言之,将列表设为List<object>
并使用.NET 4.0中的C#功能:dynamic
。
示例:
var listDiff = list1
.AsEnumerable<object>()
.Except(list2
.AsEnumerable<object>()
.Select(row => ((dynamic)row).ID));
答案 3 :(得分:2)
如果您只想Ids
中不在list1
的{{1}},您可以这样做:
list2
如果您还需要关联的var idsInList1NotInList2 = list1.Select(user1 => user1.Id)
.Except(list2.Select(user2 => user2.Id));
对象,这里是一种方式(假设Ids对于User1对象是唯一的):
User1
编辑:vc74对这个想法的看法略胜一筹;它不需要唯一性。
答案 4 :(得分:0)
尝试
list1.Where(user1 => !list2.Any(user2 => user2.Id.Equal(user1.Id)));