【发布时间】:2020-03-12 14:13:43
【问题描述】:
我有一个 MyCustomSet 类,其中 IEquatable 实现如下所示。
当我想检查所有三个集合(SetA*、SetB* 和 SetC*)的相等性时,这非常有用。但是要求要求我还需要能够检查仅 SetA*、SetB* 或 SetC* 或其组合(SetA* 和 SetB*、SetA* 和 SetC*、或 SetB* 和 SetC*)的相等性并忽略检查检查中不需要的任何其他 Set 的相等性。
目前,我正在使用 foreach 和 LINQ 来遍历 Set 以执行部分相等性检查,这很有效,但对于大型数据集。
也许答案是直视我的脸,但我看不到它,因为我不知道如何实现可以处理的 IEquatable不同的相等性检查。
是否有人可以就如何实施提供一些建议或指导?一个例子会更受欢迎。
public static class HashCode
{
public const int Start = 17;
public static int Hash<T>(this int hash, T obj)
{
var h = EqualityComparer<T>.Default.GetHashCode(obj);
return unchecked((hash * 439) + h);
}
}
public class MyCustomSetModel
{
public sealed class MyCustomSet : IEquatable<MyCustomSet>
{
public string ItemName { get; set; }
public string ItemType { get; set; }
public double SetA1 { get; set; }
public double SetA2 { get; set; }
public double SetA3 { get; set; }
public double SetB1 { get; set; }
public double SetB2 { get; set; }
public double SetB3 { get; set; }
public double SetC1 { get; set; }
public double SetC2 { get; set; }
public double SetC3 { get; set; }
public bool Equals(MyCustomSet other)
{
if (ReferenceEquals(other, null))
{
return false;
}
if (ReferenceEquals(other, this))
{
return true;
}
return
(
(this.ItemName == other.ItemName) &&
(this.ItemType == other.ItemType) &&
(this.SetA1 == other.SetA1) &&
(this.SetA2 == other.SetA2) &&
(this.SetA3 == other.SetA3) &&
(this.SetB1 == other.SetB1) &&
(this.SetB2 == other.SetB2) &&
(this.SetB3 == other.SetB3) &&
(this.SetC1 == other.SetC1) &&
(this.SetC2 == other.SetC2) &&
(this.SetC3 == other.SetC3)
);
}
public override bool Equals(object obj) => Equals(obj as MyCustomSet);
public override int GetHashCode()
{
unchecked
{
return HashCode.Start
.Hash(ItemName)
.Hash(ItemType)
.Hash(SetA1)
.Hash(SetA2)
.Hash(SetA3)
.Hash(SetB1)
.Hash(SetB2)
.Hash(SetB3)
.Hash(SetC1)
.Hash(SetC2)
.Hash(SetC3);
}
}
}
}
* 更新:*
感谢 Matthew Watson 为我指明了正确的方向。所以我实现了一个自定义比较器,如下所示。看起来它正在运行,但如果有人看到潜在的问题或更好的实施空间,请随时发表评论。
public sealed class MyCustomSetComparer : IEqualityComparer<MyCustomSet>
{
private bool _compareSetA;
private bool _compareSetB;
private bool _compareSetC;
public MyCustomSetComparer(bool compareSetA = true, bool compareSetB = true, bool compareSetC = true)
{
_compareSetA = compareSetA;
_compareSetB = compareSetB;
_compareSetC = compareSetC;
}
public bool Equals(MyCustomSet x, MyCustomSet y)
{
if (Object.ReferenceEquals(x, y))
{
return true;
}
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
{
return false;
}
bool result =
(x.ItemName == y.ItemName) &&
(x.ItemType == y.ItemType);
if (_compareSetA)
{
result = result &&
(x.SetA1 == y.SetA1) &&
(x.SetA2 == y.SetA2) &&
(x.SetA3 == y.SetA3);
}
if (_compareSetB)
{
result = result &&
(x.SetB1 == y.SetB1) &&
(x.SetB2 == y.SetB2) &&
(x.SetB3 == y.SetB3);
}
if (_compareSetC)
{
result = result &&
(x.SetC1 == y.SetC1) &&
(x.SetC2 == y.SetC2) &&
(x.SetC3 == y.SetC3);
}
return result;
}
public int GetHashCode(MyCustomSet item)
{
if (Object.ReferenceEquals(item, null))
{
return 0;
}
int hash = HashCode.Start
.Hash(item.ItemName)
.Hash(item.ItemType);
if (_compareSetA)
{
hash = hash.Hash(item.SetA1)
.Hash(item.SetA2)
.Hash(item.SetA3);
}
if (_compareSetB)
{
hash = hash.Hash(item.SetB1)
.Hash(item.SetB2)
.Hash(item.SetB3);
}
if (_compareSetC)
{
hash = hash.Hash(item.SetC1)
.Hash(item.SetC2)
.Hash(item.SetC3);
}
unchecked
{
return hash;
}
}
}
【问题讨论】:
-
您的数据集有多大,需要多长时间?
-
您应该查看
IEqualityComparer<MyCustomSet>的多个实现,然后使用accept a parameter of typeIEqualityComparer<T>的各种Linq 方法的重载,这样您就可以从被比较对象的实现外部控制比较。跨度>
标签: c# equality iequalitycomparer iequatable