C# IEnumerable.Except()如何工作?
我试图排除要添加到数据库中的实体(如果它们已经存在)。所以我决定C# IEnumerable.Except()如何工作?,c#,linq,ienumerable,C#,Linq,Ienumerable,我试图排除要添加到数据库中的实体(如果它们已经存在)。所以我决定newbillinginstances.Except(dbContext.billcinstances)将是最好的方法。然而,它根本不起作用(不排除任何实体),尽管对于List它工作得非常好 我在中阅读了.Except()的讨论和实际说明。它声明要在中使用的类。Except()应实现IEqualityComparer以使用默认比较器 实际上,MSDN文章并没有完全描述比较两个实例的过程。我仍然不明白为什么Equals()和GetHa
newbillinginstances.Except(dbContext.billcinstances)
将是最好的方法。然而,它根本不起作用(不排除任何实体),尽管对于List
它工作得非常好
我在中阅读了.Except()
的讨论和实际说明。它声明要在中使用的类。Except()
应实现IEqualityComparer
以使用默认比较器
实际上,MSDN文章并没有完全描述比较两个实例的过程。我仍然不明白为什么Equals()和GetHashObject()都必须被重写
我已经实现了IEqualityComparer
接口,并在两个方法中都设置了断点,但是在调用时,除了(IEnumerable)
之外,它没有被使用。仅当我更改为时。除了(IEnumerable,new BillInstanceComparer())
我在GetHashCode()
中有中断,但在Equals()
中没有中断
然后,我在BillInstance
类中实现了IEqualityComparer
,并期望在使用时使用它。除了(IEnumerable)
之外,这两种方法都没有达到中断
所以我有两个问题:
Equals()
?是否仅在两个实例的哈希代码相同时使用GetHashCode()
时才使用Equals()
。如果没有对象具有相同的GetHashCode()
,则不可能使用Equals()
内部,<>代码>例外()/代码>使用<代码> SET>代码>(您可以看到),这是一个您应该考虑等价的内部类。该类使用对象的散列来“索引”它们,然后使用
Equals()
检查具有相同散列的两个对象是否相同或不同,但具有相同的散列
链接到其他相关答案:代码中的某个地方隐藏了一个集合或地图/字典 这些家伙通常包含大量的bucket,这些bucket随着集合中存储的元素数量的增加而增加。元素根据散列码被划分为多个存储桶,存储桶中的实际身份比较使用equals完成 因此,哈希代码用于找到正确的bucket(为什么需要GetHashCode),然后使用equals将其与bucket中的其他元素进行比较
这就是为什么您需要同时实现这两个功能 好的,从IEnumerable源代码()中,我了解了调用
的内部结构,除了(IEnumerable)
:
enumerable1.Except(enumerable2)
调用Exceptionator(enumerable1,enumerable2,null)
其中null
应该是IEquitableComparer
的实例exceptiator()
创建内部类的实例Set
将null
传递为比较器null
所以使用属性EqualityComparer.Default
Default
属性为TElement
创建比较器,除非已经通过调用CreateComparer()
创建了比较器。具体来说,有两点我很感兴趣:
- 如果
实现了TElement
接口,那么据我所知,IEquatable
会创建一些通用的比较器。我相信它会使用IEquatable
和IEquatable.GetHashCode()
IEquatable.Equals()
- 对于一般情况(不是字节类型,不是实现IEquatable,不是NULL,不是enum)
返回实例ObjectEqualityComparer
和ObjectEqualityComparer.GetHashCode()
通常调用ObjectEqualityComparer.Equals()
的相应方法TElement
因此,这让我了解了我的案例(每个
BillInstance
的实例通常是不可变的),覆盖Object.GetHashCode()
和Object.Equals()
应该足够了,请阅读著名的博客,了解枚举方法的内部。除了(),这肯定解释了Equals()
和GetHashCode()
。只是还不清楚IEqualityComparer
的实现。它应该在哪里实现?调用Except()
的更好方法是什么?@Ralfeus WithExcept
可以做三件“事情”:直接在需要比较的类中重写GetHashCode
和等于
,或者您可以创建一个单独的类来实现IEqualityComparer
,并执行GetHashCode
和Equals
这两个操作。所有这些似乎都不起作用。第三件事是什么?@Ralfeus它在类内部实现IEquatable
接口。@Ralfeus“正确”在观察者的眼中。。。通常,您应该只在不可变字段上计算object.GetHashCode()
,否则可能会发生“不好的事情”(请参阅)。因此,如果类的所有字段都可以在其生存期内更改,则不应重写GetHashCode
IEqualityComparer
没有附加此“污名”,因此您始终可以创建一个“正确的”IEqualityComparer
。如果必须有多个比较器(区分大小写/不区分大小写),那么多个IEqualityComparer
是唯一的方法。