假设您正在编写原始的C#Object
类,并且您需要以下功能:
object1 == object2
将比较引用,除非重写此运算符object1 != object2
将始终返回对象的ACTUAL object1 == object2
因此,例如,如果我有一个Bunny
类(派生自Object
)使用ear length作为其equals方法,那么notequals方法(继承自Object
)应该如果兔子的耳长不同,则返回true。
我看到的问题是,如果我写了Object
类,那就是:
public partial class Object {
public virtual bool Equals(Object o2) {
return (this === o2);
}
public bool NotEquals(Object o2) {
return !this.Equals(o2);
}
}
那么似乎该定义会将NotEquals绑定到Object
的Equals,而不是实际派生类的equals。
有什么方法可以在不以任何方式修改C#本身的情况下工作?我并不在乎C#中的可能性,但我关心是否有一些OOP原则告诉我我不应该期待这种事情能够发挥作用。
另外,我不确定这是否是这个问题的基础,但是想法是NotEquals也是虚拟的,以便它也可以被希望它们o1 != o2
的派生类覆盖。与!(o1 == o2)
不同。这个问题的灵感来自this recent discussion。
答案 0 :(得分:6)
您提供的代码将调用派生的Equals
方法。 Equals
是虚拟的,这意味着当它被调用时,将使用“派生最多”的实现。
答案 1 :(得分:3)
NotEquals不会绑定到Object类的equal方法,它将使用派生最多的方法。你可以很容易地测试这个。而且,将notEquals设置为虚拟也很容易,因此您也可以使用自定义逻辑覆盖它。
使用这些类(忽略可怕的命名约定):
class parent
{
public virtual bool equals(parent p)
{
Console.WriteLine("parent equals");
return false;
}
public virtual bool notEquals(parent p)
{
return !this.equals(p);
}
}
class child : parent
{
public override bool equals(parent p)
{
Console.WriteLine("child equals");
return true;
}
}
然后运行:
parent p = new parent();
p.notEquals(null);
child c = new child();
c.notEquals(null);
此输出结果:
parent equals
child equals
答案 2 :(得分:3)
我可能误解了这个问题,但是在您的示例中NotEquals
中声明的Object
方法将使用在派生类上定义的Equals
方法(如果使用覆盖声明它派生类中的修饰符),而不是Object
本身。
举一个演示此行为的简单示例:
void Main()
{
BaseObject do1 = new DerivedObject();
BaseObject do2 = new DerivedObject();
do1.NotEquals(do2);
}
public class DerivedObject : BaseObject
{
public override bool Equals(BaseObject o2)
{
Console.WriteLine("OtherObject.Equals called.");
return (this == o2);
}
}
public partial class BaseObject {
public virtual bool Equals(BaseObject o2) {
return (this == o2);
}
public bool NotEquals(BaseObject o2) {
return !this.Equals(o2);
}
}
如果执行该示例,您将看到执行Console.WriteLine语句(在DerivedObject上删除override修饰符,然后不执行Console.WriteLine)。
您还可以查看documentation,其中指出:“如果没有派生类覆盖该成员,则调用最派生类中的重写成员,该成员可能是原始成员。”。
答案 3 :(得分:1)
目前还不完全清楚你要问的是什么,因为你无法改变Object
的定义,所以这个练习有些没有实际意义,但假装你可以并且实际上正在改变Object
class,this.Equals
实际上是指派生类的实现,因为Equals
是虚拟的。
特别是我不确定你的句子中的“this”是什么意思:
“在没有以任何方式修改C#本身的情况下,这个能否正常工作?”