我有一个 MyCustomSet 类,实现了 IEquatable ,如下所示。
当我要检查所有三个集合(Seta *,SetB *和SetC *)的相等性时,这效果很好。但要求表明,我还需要仅检查Seta *,SetB *或SetC *或其组合(Seta *和SetB *,Seta *和SetC *或SetB *和SetC *)的相等性并忽略检查的能力与检查中不需要的任何其他Set相等。
当前,我正在使用 foreach 和LINQ遍历Sets以执行部分相等性检查,这种方法行之有效,但对于以下情况似乎不太有效大型数据集。
也许答案是直面我,但我看不到,因为我不知道如何实现可以处理的 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;
}
}
}