Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# IEnumerable.Except()如何工作?_C#_Linq_Ienumerable - Fatal编程技术网

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)
之外,这两种方法都没有达到中断

所以我有两个问题:

  • 除了(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 With
    Except
    可以做三件“事情”:直接在需要比较的类中重写
    GetHashCode
    等于
    ,或者您可以创建一个单独的类来实现
    IEqualityComparer
    ,并执行
    GetHashCode
    Equals
    这两个操作。所有这些似乎都不起作用。第三件事是什么?@Ralfeus它在类内部实现
    IEquatable
    接口。@Ralfeus“正确”在观察者的眼中。。。通常,您应该只在不可变字段上计算
    object.GetHashCode()
    ,否则可能会发生“不好的事情”(请参阅)。因此,如果类的所有字段都可以在其生存期内更改,则不应重写
    GetHashCode
    IEqualityComparer
    没有附加此“污名”,因此您始终可以创建一个“正确的”
    IEqualityComparer
    。如果必须有多个比较器(区分大小写/不区分大小写),那么多个
    IEqualityComparer
    是唯一的方法。