具有公共字段的不同类之间的IEnumerable.Except()

时间:2010-11-01 15:59:39

标签: c# linq .net-3.5 ienumerable

是否可以将Except()用于两个具有两个不同类但具有公共字段的Lis​​t?我有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));

我做错了什么?

5 个答案:

答案 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)));