如何使用 IEquatable 查找两个 objects 之间的差异?
How to find the differences between two objects using IEquatable?
我通过在 object 上实现 IEquatable 接口来比较两个相同的 object。如果不相等,则更新数据库;否则,保持原样。这里的上下文是我需要用来自 excel sheet 的数据更新 table 并比较数据并仅在数据发生变化时更新。
下面是相同的代码
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 接口
的实际 class
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;
}
}
即使两个 object 都具有相同的值,这个条件 existingMaterialType != constructionMaterialType
也始终为真,我附上图片以供参考
我不确定上面的代码哪里做错了。谁能指出我正确的方向?
非常感谢
您没有覆盖 !=
运算符,但您可以改用 !existingMaterialType.Equals(constructionMaterialType)
。
this.NotesHTML == other.NotesHTML
将对两个列表进行引用比较,因此即使两者包含完全相同的字符串,它也会 return false
是两个列表是不同的实例。您可能想改用 this.NotesHTML.SequenceEqual(other.NotesHTML)
(如果 NotesHTML
可以是 null
,则可能需要一些调整)。
注意:GetHashCode
必须为比较相等的所有对象提供相同的结果。因此,如果您更改 Equals
方法中的任何内容,您可能还必须更改 GetHashCode
。由于比较不相等的对象不一定具有不同的哈希码,因此可以选择不考虑某些属性。此处:只需省略带有 NotesHTML
.
的行
我通过在 object 上实现 IEquatable 接口来比较两个相同的 object。如果不相等,则更新数据库;否则,保持原样。这里的上下文是我需要用来自 excel sheet 的数据更新 table 并比较数据并仅在数据发生变化时更新。
下面是相同的代码
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 接口
的实际 classpublic 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;
}
}
即使两个 object 都具有相同的值,这个条件 existingMaterialType != constructionMaterialType
也始终为真,我附上图片以供参考
我不确定上面的代码哪里做错了。谁能指出我正确的方向? 非常感谢
您没有覆盖
!=
运算符,但您可以改用!existingMaterialType.Equals(constructionMaterialType)
。this.NotesHTML == other.NotesHTML
将对两个列表进行引用比较,因此即使两者包含完全相同的字符串,它也会 returnfalse
是两个列表是不同的实例。您可能想改用this.NotesHTML.SequenceEqual(other.NotesHTML)
(如果NotesHTML
可以是null
,则可能需要一些调整)。
注意:GetHashCode
必须为比较相等的所有对象提供相同的结果。因此,如果您更改 Equals
方法中的任何内容,您可能还必须更改 GetHashCode
。由于比较不相等的对象不一定具有不同的哈希码,因此可以选择不考虑某些属性。此处:只需省略带有 NotesHTML
.