C#列表比较忽略类项

Posted

技术标签:

【中文标题】C#列表比较忽略类项【英文标题】:C# List comparison ignoring class item 【发布时间】:2015-04-16 12:25:43 【问题描述】:

我有两个数据库 DB1 和 DB2,我从每个数据库中检索销售订单并放入列表中。我现在想在 DB2 中找到 DB1 中缺少的销售订单,以便将它们添加到 DB2 中

我有listDB1ListDB2 的形式:

public class SalesOrder

      public int docNum;
      public string cardCode;
      public string cardName;
      public DateTime docDate;
      public DateTime docDueDate;                       
      public double docTotal;        
      public int lineItemCount;
      public string comments;
 

我现在想比较两个列表,忽略两个列表的 docNum,这是在比较其余元素时自动生成的。使用:

unaddedSOs = listDB1.Except(listDB2).ToList();

比较包括 docNum 在内的所有内容。如何实现我需要的,以便获得未添加的文档编号?

【问题讨论】:

尝试实现IEquatable<SalesOrder> "比较所有,包括 docNum",不,它只是默认比较引用。覆盖Equals + GetHashCode 或提供自定义IEqualityComparer<SalesOrder> @TimSchmelter:确实,我根本看不出原始版本是如何工作的,除非这两个列表包含相同项目的相同引用。 @Codor:它不会仍然比较字符串成员的引用吗? @Baldrick 尽管string 是一种引用类型,但它是通过值语义实现的,即检查是否相等并比较内容。 【参考方案1】:

您可以实现IEquatable<SalesOrder>,或创建自定义IEqualityComparer<SalesOrder>。请注意,我还建议您将这些公共字段转换为属性。

public class SalesOrder : IEquatable<SalesOrder>

    public int DocNum  get; set; 
    public string CardCode  get; set; 
    public string CardName  get; set; 
    public DateTime DocDate  get; set; 
    public DateTime DocDueDate  get; set; 
    public double DocTotal  get; set; 
    public int LineItemCount  get; set; 
    public string Comments  get; set; 

    public bool Equals(SalesOrder other)
    
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return string.Equals(cardCode, other.cardCode) &&
               string.Equals(cardName, other.cardName) &&
               docDueDate.Equals(other.docDueDate) &&
               docTotal.Equals(other.docTotal) && 
               lineItemCount == other.lineItemCount &&
               string.Equals(comments, other.comments);
    

    public override bool Equals(object obj)
    
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((SalesOrder) obj);
    

    public override int GetHashCode()
    
        unchecked
        
            var hashCode = (cardCode != null ? cardCode.GetHashCode() : 0);
            hashCode = (hashCode*397) ^ (cardName != null ? cardName.GetHashCode() : 0);
            hashCode = (hashCode*397) ^ docDueDate.GetHashCode();
            hashCode = (hashCode*397) ^ docTotal.GetHashCode();
            hashCode = (hashCode*397) ^ lineItemCount;
            hashCode = (hashCode*397) ^ (comments != null ? comments.GetHashCode() : 0);
            return hashCode;
        
    

【讨论】:

当我们在做这件事时,这个Blog article 处理了一个有争议的,但令人惊讶的优雅和灵活的技术,用于自定义实现IEquatable @Codor 那篇文章谈论的是IComparable,而不是IEquatable。 They're not the same. 确实,我弄错了。不过我相信这种方法可以推广。

以上是关于C#列表比较忽略类项的主要内容,如果未能解决你的问题,请参考以下文章

c# - 如何从忽略字符串空格的列表中检索字符串元素?

基于嵌套列表中包含的 id 元素比较两个通用列表的最有效方法 (C#)

C# 测试 - 比较自定义类型列表

比较两个通用列表C#的最快方法[关闭]

C#比较两个列表之间的特定项目属性[重复]

c# 在 LINQ 查询返回的列表中查找项目并将其值与列表中的另一个项目进行比较