19

List1包含项目{ A, B }List2包含项目{ A, B, C }

我需要的是{ C }在我使用除了 Linq 扩展时返回。相反,我被返回{ A, B },如果我在我的表达式中翻转列表,结果是{ A, B, C }.

我误解了Except的意思吗?是否有另一个我没有看到使用的扩展程序?

到目前为止,我已经浏览并尝试了许多关于此问题的不同帖子,但均未成功。

var except = List1.Except(List2); //This is the line I have thus far

编辑:是的,我在比较简单的对象。没用过IEqualityComparer,学习一下很有意思。

谢谢大家的帮助。问题是没有实现比较器。链接的博客文章和下面的示例很有帮助。

4

5 回答 5

18

如果您将引用类型存储在列表中,则必须确保有一种方法可以比较对象是否相等。否则,将通过比较它们是否引用相同的地址来检查它们。

您可以实现IEqualityComparer<T>并将其作为参数发送到except()函数。这是一篇博文,您可能会觉得有帮助。

编辑原始博客文章链接已损坏,已在上面替换

于 2013-05-29T22:46:31.233 回答
9

所以只是为了完整性......

// Except gives you the items in the first set but not the second
    var InList1ButNotList2 = List1.Except(List2);
    var InList2ButNotList1 = List2.Except(List1);
// Intersect gives you the items that are common to both lists    
    var InBothLists = List1.Intersect(List2);

编辑:由于您的列表包含您需要为您的班级传递 IEqualityComparer 的对象...这是您的 except 与基于组成对象的示例 IEqualityComparer 的样子... :)

// Except gives you the items in the first set but not the second
        var equalityComparer = new MyClassEqualityComparer();
        var InList1ButNotList2 = List1.Except(List2, equalityComparer);
        var InList2ButNotList1 = List2.Except(List1, equalityComparer);
// Intersect gives you the items that are common to both lists    
        var InBothLists = List1.Intersect(List2);

public class MyClass
{
    public int i;
    public int j;
}

class MyClassEqualityComparer : IEqualityComparer<MyClass>
{
    public bool Equals(MyClass x, MyClass y)
    {
        return x.i == y.i &&
               x.j == y.j;
    }

    public int GetHashCode(MyClass obj)
    {
        unchecked
        {
            if (obj == null)
                return 0;
            int hashCode = obj.i.GetHashCode();
            hashCode = (hashCode * 397) ^ obj.i.GetHashCode();
            return hashCode;
        }
    }
}
于 2013-05-29T22:36:59.460 回答
7

您只是混淆了参数的顺序。我可以看到这种混淆出现在哪里,因为官方文档并没有它可能的帮助:

通过使用默认相等比较器比较值来产生两个序列的集合差。

除非您精通集合论,否则可能不清楚集合差异实际上是什么——这不仅仅是集合之间的差异。实际上,Except返回第一个集合中不在第二个集合中的元素列表。

尝试这个:

var except = List2.Except(List1); // { C }
于 2013-05-29T22:15:09.983 回答
0

编写自定义比较器似乎确实可以解决问题,但我认为https://stackoverflow.com/a/12988312/10042740是一个更加简单和优雅的解决方案。

它覆盖了对象定义类中的 GetHashCode() 和 Equals() 方法,然后默认的比较器会发挥它的魔力,而无需额外的代码弄乱这个地方。

于 2020-07-11T20:03:10.120 回答
-1

仅供参考:我想比较系统连接和可用的 USB 驱动器。

所以这是实现接口 IEqualityComparer 的类

public class DriveInfoEqualityComparer : IEqualityComparer<DriveInfo>
{
    public bool Equals(DriveInfo x, DriveInfo y)
    {
        if (object.ReferenceEquals(x, y))
            return true;
        if (x == null || y == null)
            return false;
        // compare with Drive Level
        return x.VolumeLabel.Equals(y.VolumeLabel);
    }

    public int GetHashCode(DriveInfo obj)
    {
        return obj.VolumeLabel.GetHashCode();
    }
}

你可以像这样使用它

var newDeviceLst = DriveInfo.GetDrives()
                            .ToList()
                            .Except(inMemoryDrives, new DriveInfoEqualityComparer())
                            .ToList();
于 2018-09-21T11:59:26.720 回答