【问题标题】:C# List comparison ignoring class itemC#列表比较忽略类项
【发布时间】: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 是一种引用类型,但它是通过值语义实现的,即检查是否相等并比较内容。

标签: c#


【解决方案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,而不是IEquatableThey're not the same.
  • 确实,我弄错了。不过我相信这种方法可以推广。
猜你喜欢
  • 1970-01-01
  • 2021-08-31
  • 1970-01-01
  • 1970-01-01
  • 2016-12-03
  • 2018-07-05
  • 1970-01-01
  • 2015-04-20
  • 2014-03-05
相关资源
最近更新 更多