我有一个包含十个属性的类,我正在寻找在这些属性中具有相同值的对象,但两个特定属性除外。
我想扩展一个具有我想要比较的八个属性的基类,然后扩展这个基类,调用基本Equals
方法?
决定这一点的代码密集程度最低的是什么?
答案 0 :(得分:0)
每当您希望比较自定义类的两个实例的值相等(即两个具有相同值或值的对象)而不是参考质量(两个对象引用引用相同的底层对象)时,您必须在对象的设计中考虑到了。有一个pattern you can follow to do this。简而言之,它涉及实现System.IEquatable<T>
接口,该接口定义了带有签名bool Equals(MyClass other)
的方法。当true
具有相同的“值”为other
对象时,您可以实现此方法以返回this
。以下是简单对象的基本示例,该对象具有4个确定其值相等的属性:
class MyClass : IEquatable<MyClass>
{
public int ImportantProperty1 { get; set; }
public int ImportantProperty2 { get; set; }
public int ImportantProperty3 { get; set; }
public int ImportantProperty4 { get; set; }
public int NonImportantProperty { get; set; }
public bool Equals(MyClass other)
{
return
(!Object.ReferenceEquals(this, null)) &&
(this.ImportantProperty1 == other.ImportantProperty1) &&
(this.ImportantProperty2 == other.ImportantProperty2) &&
(this.ImportantProperty3 == other.ImportantProperty3) &&
(this.ImportantProperty4 == other.ImportantProperty4);
}
}
使用上面的代码,您将能够执行以下操作:
MyClass a = new MyClass() { };
MyClass b = new MyClass() { };
if (a.Equals(b))
Console.WriteLine("a and b are equal");
这是最低限度的。但是,如链接文章中所述,您可能需要考虑以下优化:
重写virtual Object.Equals(Object)
方法,以便调用特定于类型的Equals方法。这样您就可以将MyClass
与其他类型的对象进行比较:
public override bool Equals(object obj)
{
return this.Equals(obj as MyClass);
}
添加到bool Equals(MyClass)
方法检查以查看other
是否引用与this
相同的对象:
public bool Equals(MyClass other)
{
if (Object.ReferenceEquals(this, other))
return true;
return
(!Object.ReferenceEquals(this, null)) &&
(this.ImportantProperty1 == other.ImportantProperty1) &&
(this.ImportantProperty2 == other.ImportantProperty2) &&
(this.ImportantProperty3 == other.ImportantProperty3) &&
(this.ImportantProperty4 == other.ImportantProperty4);
}
覆盖Object.GetHashCode()
方法,以便两个具有值相等的对象生成相同的哈希代码。这是我在这种情况下实现此方法时使用的模式:
public override int GetHashCode()
{
unchecked {
int hash = 17;
hash = hash * 23 + ImportantProperty1.GetHashCode();
hash = hash * 23 + ImportantProperty2.GetHashCode();
hash = hash * 23 + ImportantProperty3.GetHashCode();
hash = hash * 23 + ImportantProperty4.GetHashCode();
return hash;
}
}
可选择覆盖==
和!=
运算符。除非这些被覆盖,否则它们将默认引用相等。有关示例,请参阅链接的文章。
以下是我的完整示例:
namespace ValueEquality
{
class MyClass : IEquatable<MyClass>
{
public int ImportantProperty1 { get; set; }
public int ImportantProperty2 { get; set; }
public int ImportantProperty3 { get; set; }
public int ImportantProperty4 { get; set; }
public int NonImportantProperty { get; set; }
public bool Equals(MyClass other)
{
if (Object.ReferenceEquals(this, other))
return true;
return
(!Object.ReferenceEquals(this, null)) &&
(this.ImportantProperty1 == other.ImportantProperty1) &&
(this.ImportantProperty2 == other.ImportantProperty2) &&
(this.ImportantProperty3 == other.ImportantProperty3) &&
(this.ImportantProperty4 == other.ImportantProperty4);
}
public override bool Equals(object obj)
{
return this.Equals(obj as MyClass);
}
public override int GetHashCode()
{
unchecked {
int hash = 17;
hash = hash * 23 + ImportantProperty1.GetHashCode();
hash = hash * 23 + ImportantProperty2.GetHashCode();
hash = hash * 23 + ImportantProperty3.GetHashCode();
hash = hash * 23 + ImportantProperty4.GetHashCode();
return hash;
}
}
}
class Program
{
static void Main(string[] args)
{
MyClass a = new MyClass() { };
MyClass b = new MyClass() { };
if (a.Equals(b))
Console.WriteLine("a and b are equal");
}
}
}