IEnumerable.Except()如何工作?

时间:2016-03-24 08:02:24

标签: c# linq ienumerable

我试图排除要添加到数据库中的实体(如果它们已经存在)。所以我决定newBillInstances.Except(dbContext.BillInstances)是最好的方法。然而,它根本不起作用(没有实体被排除)但是List<string>它完美地运作。

我在this中阅读MSDN.Except()次讨论和.Except()的实际解密。它声明要在IEqualityComparer<T>中使用的类应该实现IEqualityComparer<BillInstance>以使用默认比较器。

实际上,MSDN文章并没有完全描述两个实例的比较过程。我仍然不明白为什么必须重写Equals()和GetHashObject()。

我已经实现了.Except(IEnumerable)接口,并在两种方法中都设置了断点,但在调用.Except(IEnumerable, new BillInstanceComparer())时却没有使用它。只有当我更改为GetHashCode()时我才会在Equals()中咳嗽但是在IEqualityComparer<BillInstance>中没有休息。

然后我在BillInstance课程中实现了.Except(IEnumerable),并期望在使用.Except(IEnumerable)时使用Equals(),但在这两种方法中都没有中断。

所以我有两个问题:

  1. 使用var output = []; $.each(datatogen, function (key, value) { var datatomo = {}; $.each(value, function (key1, value1) { datatomo.Catagories = value1; datatomo.Value1 = value1 ; }); output.push(datatomo); }); 应该怎么做?
  2. 为什么{{#each lines}} <tr> {{#each columns as |column|}} {{#ifCond column}} {{/ifCond}} {{/each}} </tr> {{/each}} 根本不被使用?仅在两个实例的哈希码相同的情况下使用它吗?

3 个答案:

答案 0 :(得分:4)

因为仅当两个对象具有相同的Equals()时才使用GetHashCode()。如果没有具有相同GetHashCode()的对象,则无法使用Equals()

Except()内部Set<>使用Equals()(您可以看到here),这是一个内部类,您应该认为它等同于HashSet<>。此类使用对象的哈希来“索引”它们,然后使用$retina: 'only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx)'; &:after { content: ''; position: absolute; top: 5px; left: 0; width: 0; height: 36px; display: block; opacity: 0; z-index: -1; transition: width ease .4s, opacity ease .4s; background: url(~img/layout/menu-hover.png) 0 0 / 100% 36px repeat-x; @media #{$retina} { background-image: url(~img/layout/menu-hover@2x.png); } } 检查具有相同哈希的两个对象是相同还是不同但是具有相同的哈希值。

链接到其他相关答案:https://stackoverflow.com/a/371348/613130

答案 1 :(得分:0)

代码中的某处隐藏了一个集合或地图/字典。

这些人通常包含许多桶,这些桶随着存储在集合中的元素数量而增长。基于哈希码将元素划分为桶,并且使用equals完成桶内的实际身份比较。

因此哈希码用于查找正确的存储桶(为什么需要GetHashCode),其中equals用于将其与存储桶中的其他元素进行比较。

这就是你需要实现这两者的原因。

答案 2 :(得分:0)

好的,从IEnumerable来源(thanks to m0sa)我已经理解了调用Except(IEnumerable)的内幕:

  1. enumerable1.Except(enumerable2)调用ExceptIterator(enumerable1, enumerable2, null),其中null应该是IEquitableComparer的实例。

  2. ExceptIterator()创建一个内部类Set的实例,将null作为比较器传递。

  3. 由于比较器为null,因此使用了属性EqualityComparer<TElement>.Default

  4. Default属性为TElement创建一个比较器,除非它已通过调用CreateComparer()创建。特别是2分对我来说很有意思:

    • 如果TElement实现了IEquatable接口,那么就我所知,创建了IEquatable的一般通用比较器。我相信它会使用IEquatable.GetHashCode()IEquatable.Equals()

    • 对于一般情况(不是字节类型,不实现IEquatable,不是Nullable,不是枚举),返回ObjectEqualityComparer实例。 ObjectEqualityComparer.GetHashCode()ObjectEqualityComparer.Equals()通常会调用TElement的相应方法。

  5. 所以这让我理解了我的案例(BillInstance的每个实例通常都是不可变的)它应该足以覆盖Object.GetHashCode()Object.Equals()