【问题标题】:How does Equals implicitly compare lists if it is intended to compare individual elements?如果 Equals 旨在比较单个元素,它如何隐式比较列表?
【发布时间】:2017-06-19 00:22:09
【问题描述】:

我有一个具有 3 个属性的 Vendor 对象:VendorId、CompanyName 和 Email:

我发现我可以重写 Equals 方法来比较两个供应商:

public override bool Equals(object obj)
        {
            if (obj == null || this.GetType() != obj.GetType())
                return false;
            Vendor v = (Vendor)obj;
            if (v != null
                && v.CompanyName == this.CompanyName
                && v.Email == this.Email
                && v.VendorId == this.VendorId)
                return true;
            return base.Equals(obj);
        }

...否则 C# 无法做到,因为它不知道两个供应商对象何时相等,除非我专门指示它比较两个供应商的每个对象属性。

现在,在我的单元测试中,我发现我实际上不仅可以比较供应商,还可以比较供应商列表:

CollectionAssert.AreEqual(listOfVendors1, listOfVendors2);

我得到的列表如下:

var listOfVendors1 = new List<Vendor>() {
new Vendor() { VendorId = 1, CompanyName="comp1", Email="e@yahoo.com" },
new Vendor() { VendorId = 2, CompanyName="comp2", Email="f@yahoo.com" }
};

对于第二个列表:

var listOfVendors2 = new List<Vendor>() {
new Vendor() { VendorId = 1, CompanyName="comp1", Email="e@yahoo.com" },
new Vendor() { VendorId = 2, CompanyName="comp2", Email="f@yahoo.com" }
};

我注意到当 CollectionAssert.AreEqual(listOfVendors1, listOfVendors2);处理完毕后,我的自定义 Equals 方法被调用,首先是 listOfVendors1.First() 和 listOfVendors2.First(),如果两个供应商的属性相等,则再次调用 Equals 方法,比较两者中的第二个元素列表。

我想了解使这成为可能的机制,因为我没有专门遍历这两个列表的元素。如何,何时完成迭代?我很困惑。

如果 Equals 旨在比较单个元素,它如何隐式比较(?)列表?例如Vendor1.Equals(Vendor2)

【问题讨论】:

  • CollectionAssert.AreEqual 的文档指出:“如果两个集合具有相同顺序和数量的相同元素,则它们相等。如果它们的值相等,则元素相等,而不是如果它们引用到同一个对象。元素的值默认使用Equals 进行比较。" - 其中哪一部分不清楚?
  • 我对查找和阅读文档相关部分感到厌烦的部分。感谢您指出 UnholySheep。

标签: c#


【解决方案1】:

我想了解使这成为可能的机制,因为我没有专门遍历这两个列表的元素。如何,何时完成迭代?我很困惑。

SequenceEqual 方法与您的CollectionAssert.AreEqual 方法几乎相同。如果你想知道它是如何工作的,你可以在这里阅读源代码:

https://github.com/Microsoft/referencesource/blob/master/System.Core/System/Linq/Enumerable.cs

总而言之:它在同一个循环中迭代两个序列,并在每对元素上调用 Equal。

如果您需要做的不是比较两个序列中的元素对是否相等,您可以使用Zip 序列运算符;如果您查看它的实现,您会发现它与SequenceEqual 毫不相似。

【讨论】:

    【解决方案2】:

    CollectionAssert.AreEqual(listOfVendors1, listOfVendors2);

    将在内部迭代您的列表并检查所有项目是否与值和顺序匹配。要确定对象的相等性,它将使用您的自定义 Equals 方法(如果可用),否则它将使用默认比较。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-28
      • 1970-01-01
      • 2020-02-21
      • 2020-07-04
      • 1970-01-01
      相关资源
      最近更新 更多