Reputation: 305
I would be so gratefull if you could tell me exactly why can not we declare operator methods virtual in a base class so we can override them in derived classes.
After scouring the internet I could not find a solid answer.
In case of binary operators, It is logical that overriding would make no sense for the compiler but what about unary operators like ++
etc.
Why isn't it possible to tell the compiler to cal ldifferent binary operator methods based on the object type the reference variable is pointing to?
I apologize if the question is too theoretical and is lacking practicality.
Upvotes: 0
Views: 111
Reputation: 117009
Let's take this simple example:
void Main()
{
var booking1 = new Booking() { Name = "Elon", Pax = 2 }; //romatic dinner
var booking2 = booking1 + 2; // two friends are coming :-(
var booking3 = -3 + booking2; // everyone else bailed.
}
public class Booking
{
public string Name { get; init; }
public int Pax { get; init; }
public static Booking operator +(Booking booking, int paxDelta) =>
new Booking() { Name = booking.Name, Pax = booking.Pax + paxDelta };
public static Booking operator +(int paxDelta, Booking booking) =>
booking + paxDelta;
}
This allows me to create a booking and then change the number of people by doing either Booking + int
or int + Booking
.
Now if we change to a hypothetical instance methods this is what we get:
public Booking operator +(int paxDelta) =>
new Booking() { Name = this.Name, Pax = this.Pax + paxDelta };
// Can't implement!
//public Booking +(Booking booking) => booking + ????;
It would mean I could only ever type Booking + int
, not the other way around.
The solution around this is quite simple though. Just do this:
public class Booking
{
public string Name { get; init; }
public int Pax { get; init; }
protected virtual Booking AddInternal(int paxDelta) =>
new Booking() { Name = this.Name, Pax = this.Pax + paxDelta };
public static Booking operator +(Booking booking, int paxDelta) =>
booking.AddInternal(paxDelta);
public static Booking operator +(int paxDelta, Booking booking) =>
booking + paxDelta;
}
public class SubBooking : Booking
{
protected override Booking AddInternal(int paxDelta)
{
var booking = base.AddInternal(paxDelta);
return new SubBooking()
{
Name = $"{this.Name}!",
Pax = this.Pax
};
}
}
Now I have symmetry and I have overridability.
Upvotes: 2
Reputation: 38094
There are some reasons based on this post by Eric Lippert:
If you define an operator+ that takes a C and an int, then c+2 is legal but 2+c is not, and that badly breaks our intuition about how the addition operator should behave.
and:
These and other difficulties along with the ease of building your own single (or double!) virtual dispatch mechanisms out of static mechanisms, makes it easy to decide to not add instance or virtual operator overloading to C#.
Upvotes: 2