我有一个实现为[[IEquatable的MyCustomSet类,如下所示。
当我要检查所有三个集合(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; } } }
IEqualityComparer<T>
而不是IEqualityComparer<T>
的完美时机。我建议仅在对类型的相等性有一个显而易见的自然定义时才实施IEquatable<T>
。当存在多个相等选项时,没有一个选项比其他选项更合理时,请以几种不同的实现类型或以创建为参数的单个实现类型来实现IEquatable<T>
。