Home > Enterprise >  Why isn't It possible to declare operator or conversion methods virtual ? C#
Why isn't It possible to declare operator or conversion methods virtual ? C#

Time:07-27

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.

CodePudding user response:

There are some reasons based on this post by Eric Lippert:

  • it helps to avoid of breaking operator symmetry:

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.

  • C# also makes a distinction between values and references, but it would be very strange if instance operator overloads were only definable on non-nullable value types, and it would also be strange if c 2 could throw a null reference exception.

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#.

CodePudding user response:

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.

  • Related