如何使用 IEquatable 查找两个对象之间的差异?

问题描述

我通过在对象上实现 IEquatable 接口来比较两个相同的对象。如果它们不相等,则更新数据库;否则,保持原样。这里的上下文是我需要使用来自 Excel 工作表的数据更新表格并比较数据并仅在数据更改时更新。

下面是相同的代码

var constructionMaterialTypes = package.GetobjectsFromSheet<ConstructionMaterialTypeExcelDto>(ConstructionDataSheetNames.CONSTRUCTION_MATERIAL_TYPE,ConstructionDataTableNames.ConstructionMaterialType);
var materialTypes = new List<ConstructionMaterialType>();
foreach (var materialType in constructionMaterialTypes)
{
    var materialTypeId = GetGuidFromMD5Hash(materialType.name);
    List<string> materialTypeNotes = new();

    if (!string.IsNullOrEmpty(materialType.notes))
    {
        materialTypeNotes.Add(materialType.notes);
    }

    var existingMaterialType = ctx.ConstructionMaterialTypes.SingleOrDefault(cm => cm.Id == materialTypeId);

    var constructionMaterialType = new ConstructionMaterialType
    {
        Id = materialTypeId,Name = materialType.name,NotesHTML = materialTypeNotes
    };

    if (existingMaterialType != default)
    {
        if (existingMaterialType != constructionMaterialType) // Object comparison happening here 
        {
            existingMaterialType.Name = materialType.name;
            existingMaterialType.NotesHTML = materialTypeNotes;
        }
    }
    else
    {                       
        materialTypes.Add(constructionMaterialType);                       
    }
}

然后下面是我实现 Iequatable 接口的实际类

public sealed class ConstructionMaterialType : IIdentity<Guid>,IEquatable<ConstructionMaterialType>
{
    [Key]
    public Guid Id { get; set; }
    public string Name { get; set; }
    public List<string> NotesHTML { get; set; }
    public bool Equals(ConstructionMaterialType other)
    {
        if (other is null)
            return false;

        return this.Id == other.Id
            && this.Name == other.Name
            && this.NotesHTML == other.NotesHTML;
    }
    public override bool Equals(object obj) => Equals(obj as ConstructionMaterialType);
    public override int GetHashCode()
    {
        int hash = 19;
        hash = hash * 31 + (Id == default ? 0 : Id.GetHashCode());
        hash = hash * 31 + (Name == null ? 0 : Name.GetHashCode(StringComparison.OrdinalIgnoreCase));
        hash = hash * 31 + (NotesHTML == null ? 0 : NotesHTML.GetHashCode());
        return hash;
    }
}

此条件 existingMaterialType != constructionMaterialType 始终为真,即使两个对象都具有相同的值,并且我也附上了图像以供参考

enter image description here

enter image description here

我不确定我在上面的代码中哪里做错了。有人可以指出我正确的方向吗? 非常感谢提前

解决方法

  1. 您没有覆盖 != 运算符,但可以改用 !existingMaterialType.Equals(constructionMaterialType)

  2. this.NotesHTML == other.NotesHTML 将对两个列表进行引用比较,因此即使两个列表包含完全相同的字符串,它也会返回 false 是两个列表是不同的实例。您可能想改用 this.NotesHTML.SequenceEqual(other.NotesHTML)(如果 NotesHTML 可以是 null,则可能需要单独调整)。

注意:GetHashCode 必须为所有比较相等的对象提供相同的结果。因此,如果您更改 Equals 方法中的任何内容,您可能还必须更改 GetHashCode。由于比较不相等的对象不必具有不同的哈希码,因此可以选择不考虑某些属性。此处:只需省略带有 NotesHTML 的行。