3

Say you were writing the original C# Object class and you wanted the following functionality:

  1. object1 == object2 will compare references unless this operator is overridden
  2. object1 != object2 will always return the inverse of the object's ACTUAL object1 == object2

So, for example, if I have a Bunny class (derived from Object) which uses ear lengths as its equals method, then the notequals method (inherited from Object) should return true if the bunnies have different ear lengths.

The problem that I see is that if I write my Object class something like:

public partial class Object {
    public virtual bool Equals(Object o2) {
       return (this === o2);
    }

    public bool NotEquals(Object o2) {
       return !this.Equals(o2);
    }
}

then it seems like that definition will bind NotEquals to Object's Equals, not the actual derived class's equals.

Is there some way that this can work without modifying C# itself in any way? I don't care so much that it's possible in C# but I care if there's some OOP principle which tells me that I shouldn't expect this sort of thing to work.

Also, I'm not sure whether or not this is fundamental to the question, but the idea is for NotEquals to be virtual as well so that it too can be overridden by derived classes which want their o1 != o2 to be different from !(o1 == o2). This question is inspired by this recent discussion.

Community
  • 1
  • 1
Rag
  • 6,405
  • 2
  • 31
  • 38

4 Answers4

6

The code you've provided will call the derived Equals method. Equals is virtual, and that means that when it is called, the "most derived" implementation will be used.

Paul Phillips
  • 6,093
  • 24
  • 34
3

NotEquals will not bind to the Object class's equal method, it will use the most derived method. You could've easily tested this. And it's also easy to make notEquals virtual, so you could override that with custom logic as well.

Using these classes (ignore the horrible naming conventions):

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;
    }
}

Then running this:

parent p = new parent();
p.notEquals(null);

child c = new child();
c.notEquals(null);

Results in this output:

parent equals
child equals
Coeffect
  • 8,772
  • 2
  • 27
  • 42
3

I might be misunderstanding the question, but the NotEquals method declared in Object in your example will use the Equals method defined on the derived class (if it is declared with the override modifier in the derived class), not on Object itself.

Take this simple example that demonstrates this behavior:

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);
    }
}

If you execute that example you'll see that the Console.WriteLine statement is executed (take away the override modifier on DerivedObject, and then the Console.WriteLine will not be executed).

You can also view the documentation, which states: "The overriding member in the most derived class is called, which might be the original member, if no derived class has overridden the member.".

rsbarro
  • 27,021
  • 9
  • 71
  • 75
1

It's not entirely clear what you're trying to ask because you can't change the definition of Object so the exercise is somewhat moot, but pretending that you can and are actually changing the Object class, this.Equals would in fact refer to the derived class's implementation because the Equals is virtual.

In particular I'm not sure what you mean by "this" in your sentence:

"Is there some way that this can work without modifying C# itself in any way?"

Davy8
  • 30,868
  • 25
  • 115
  • 173