C# Equals方法继承混乱
假设我有一个类,C# Equals方法继承混乱,c#,inheritance,C#,Inheritance,假设我有一个类,ClassB,它通过添加另一个不在ClassA中的属性来扩展另一个类,ClassA。以下方法有效吗 public bool Equals(ClassB other) { return this.ExtraProp == other.ExtraProp && base.Equals(ClassB); } 为什么应该允许我将ClassB对象传递给ClassA的equals方法(只接受ClassA对象)?继承就是这样工作的吗?因为ClassB对象是ClassA
ClassB
,它通过添加另一个不在ClassA
中的属性来扩展另一个类,ClassA
。以下方法有效吗
public bool Equals(ClassB other)
{
return this.ExtraProp == other.ExtraProp && base.Equals(ClassB);
}
为什么应该允许我将
ClassB
对象传递给ClassA
的equals方法(只接受ClassA
对象)?继承就是这样工作的吗?因为ClassB
对象是ClassA
对象。您可以在任何地方将ClassB
对象视为ClassA
对象。这就是多态性的本质
至于它是否会实际返回正确的结果,这将取决于ClassA
的实现。某些实现不会像代码所期望的那样工作,但其他实现会
让我们在这里用一个具体的例子。假设这是ClassA
的定义:
public class ClassA
{
public int first;
public int second;
public bool Equals(ClassA other)
{
if (other == null) return false;
return first == other.first &&
second == other.second;
}
}
现在让我们假设我们有这些对象:
ClassA a = new ClassA() { first = 1, second = 2 };
ClassB b = new ClassB() { first = 1, second = 2, third = 3 };
此处a.Equals(b)
将为true
。它有两个被检查的属性,因此它认为它们相等。您希望这些对象被视为相等吗
另一种实施方式是:
public bool Equals(ClassA other)
{
if (other == null) return false;
if (other.GetType() != typeof(ClassA)) return false;
return first == other.first &&
second == other.second;
}
这里我们显式地检查(在运行时而不是在编译时授予)以确保另一个实例不是更派生的类型。在这种情况下,
a.Equals(b)
将为false。您可以实现您喜欢的任何语义。因为ClassB
对象是ClassA
对象。您可以在任何地方将ClassB
对象视为ClassA
对象。这就是多态性的本质
至于它是否会实际返回正确的结果,这将取决于ClassA
的实现。某些实现不会像代码所期望的那样工作,但其他实现会
让我们在这里用一个具体的例子。假设这是ClassA
的定义:
public class ClassA
{
public int first;
public int second;
public bool Equals(ClassA other)
{
if (other == null) return false;
return first == other.first &&
second == other.second;
}
}
现在让我们假设我们有这些对象:
ClassA a = new ClassA() { first = 1, second = 2 };
ClassB b = new ClassB() { first = 1, second = 2, third = 3 };
此处a.Equals(b)
将为true
。它有两个被检查的属性,因此它认为它们相等。您希望这些对象被视为相等吗
另一种实施方式是:
public bool Equals(ClassA other)
{
if (other == null) return false;
if (other.GetType() != typeof(ClassA)) return false;
return first == other.first &&
second == other.second;
}
这里我们显式地检查(在运行时而不是在编译时授予)以确保另一个实例不是更派生的类型。在这种情况下,
a.Equals(b)
将为false。您可以实现您喜欢的任何语义。Employee
继承自Human
Employee
的属性不仅仅是人
,但它仍然是人
如果你实现了一个
Human.Equals()
你可以传递一个员工
,因为在内心深处员工
仍然是人
。。。。但是你不能像对待员工一样对待人类,因为不是所有的人类都有收入属性
Employee
的属性不仅仅是人
,但它仍然是人
如果你实现了一个
Human.Equals()
你可以传递一个员工
,因为在内心深处员工
仍然是人
。。。。但你不能像对待员工一样对待人类,因为并非所有人类都具有多态性的收入属性。这也是Liskov替代原理的作用=)+1。很好的解释。但在这里你必须小心。如果重写ClassB.Equals
,则可以得到如下情况:A.Equals(B)==true和B.Equals(A)==false
。这可能非常令人困惑。正如您所说,这取决于您喜欢的语义。我被烧坏的次数已经够多了,所以我更喜欢您的第二个实现:两个对象不相等,除非它们是相同的类型。如果我需要继承的类型作为相等进行比较,我将为多态性创建一个自定义相等比较器。+1。这也是Liskov替代原理的作用=)+1。很好的解释。但在这里你必须小心。如果重写ClassB.Equals
,则可以得到如下情况:A.Equals(B)==true和B.Equals(A)==false
。这可能非常令人困惑。正如您所说,这取决于您喜欢的语义。我被烧坏的次数已经够多了,所以我更喜欢您的第二个实现:两个对象不相等,除非它们是相同的类型。如果我需要继承的类型作为相等进行比较,我将创建一个自定义相等比较器。