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

How to find the differences between two objects using IEquatable?

提问人:Glory Raj 提问时间:6/23/2021 最后编辑:Glory Raj 更新时间:6/23/2021 访问量:230

问:

我通过在对象上实现 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

在此处输入图像描述

在此处输入图像描述

我不确定我在上面的代码中哪里做错了。谁能为我指出正确的方向? 提前非常感谢

C# .net-core 接口 iequatable

评论

0赞 Klaus Gütter 6/23/2021
1. 您没有覆盖运算符,但您可以改用。2.代替你可能想用;在这种情况下,也需要调整!=!existingMaterialType.Equals(constructionMaterialType)this.NotesHTML == other.NotesHTMLthis.NotesHTML.SequenceEquals(other.NotesHTML) GetHashCode()
0赞 Glory Raj 6/23/2021
@KlausGütter。我已经使用过,但它仍然失败,是的,没有使用运算符!existingMaterialType.Equals(constructionMaterialType)!=
0赞 Klaus Gütter 6/23/2021
您是否尝试调试过它?我敢打赌问题出在this.NotesHTML == other.NotesHTML
0赞 Space 6/23/2021
问题确实是接缝,因为当您将 a 等同于另一个时,它只是检查引用是否相等,而不是检查列表中的项目是否相同。您必须使用或编写自己的相等方法this.NotesHTML == other.NotesHTMLListList(System.Linq) Enumerable.SequenceEqualList

答:

1赞 Klaus Gütter 6/23/2021 #1
  1. 您没有重写运算符,但可以改用。!=!existingMaterialType.Equals(constructionMaterialType)

  2. this.NotesHTML == other.NotesHTML将对两个列表进行引用比较,因此即使两者都包含完全相同的字符串,它也会返回两个列表是不同的实例。您可能想改用(如果可以的话,可能需要 sone 适应)。falsethis.NotesHTML.SequenceEqual(other.NotesHTML)NotesHTMLnull

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

评论

0赞 Glory Raj 6/23/2021
我确实尝试过同样的方法,但它仍然有些失败,你所说的gethashcode是什么意思需要调整this.NotesHTML.SequenceEqual(other.NotesHTML)
0赞 Glory Raj 6/23/2021
谢谢,它适用于第一个版本