0

Suppose I have a class:

 public class Vector
 {
   public float X { get; set; }

   public Vector(float xvalue)
   {
       X = xvalue;
   }

   public static Vector operator +(Vector v1, Vector v2) 
   {
       return new Vector(v1.X + v2.X);
   }
 }

Have a derived class:

 public class MyVector : Vector
 {
     public static MyVector operator +(MyVector v1, MyVector v2)
     {
         return new MyVector(v1.X + v2.X);
     }

    public MyVector(float xvalue):base(xvalue)
    {

    }
 }

No if I execute folowing code:

 Vector v1 = new MyVector(10);    //type MyVector

 Vector v2 = new MyVector(20);    //type MyVector

 Vector v3 = v1 + v2;             //executed operator is of Vector class

Here is executed Vector's + operator, but the type of v1 and v2 is MyVector, so v3 is Vector type at this point.

Why this happens?

2
  • 2
    What you are expecting is that operator overload resolution uses double virtual dispatch but in reality it uses non virtual dispatch. It would be awesome if operators were resolved via double virtual dispatch, but the language does not support that feature. See blogs.msdn.com/b/ericlippert/archive/2009/04/09/… for more thoughts on this. Commented Jul 20, 2011 at 20:28
  • Got it, the problem that by just looking on code executed I would say, v3 is MyVector or may be other derived type, but not based one. awesome... Instead here dominates rule of just "simple" static function rule. Commented Jul 20, 2011 at 20:31

2 Answers 2

3

Because the type of the variables v1 and v2 are Vector, not MyVector. Operator overloads are static methods that are resolved by the compiler at compile-time, not at runtime; they cannot be overridden.

v1 and v2 will have to be typed MyVector for the compiler to select the overload defined in the MyVector class.

Optionally, define a method public virtual Vector Add(Vector other) on the Vector class and have MyVector override it. Then call this method from the operator+ method of Vector and this will work as you expected. (MyVector would then not need to define operator+ itself.)

Sign up to request clarification or add additional context in comments.

1 Comment

@Tigran: Not quite, but close. The compiler looks at the compile-time type of both sides and makes a list of all the "+" operators available on both types. It then does overload resolution on that list as though the operation was a call to a two-argument method "operator+(a, b)".
1

Like cdhowie answered, the method resolution is done at compile type.

But if you're working with C# 4.0, you can try the following.

void foo()
{
   Vector v1 = new MyVector(10);    // type MyVector
   Vector v2 = new MyVector(20);    // type MyVector
   Vector v3 = v1 + v2;             // Vector.operator + called
   bar(v1, v2);
}

void bar(Vector p_v1, Vector p_v2)
{
   dynamic v1 = p_v1;               // dynamic type
   dynamic v2 = p_v2;               // dynamic type
   Vector v3 = v1 + v2;             // MyVector.operator + called
}

To see that in the bar() method, the method call resolution will be done at runtime, using the true type of v1 and v2, instead of the perceived type at compile time (as in foo()).

:-)

P.S.: Delaying type resolution at runtime can be slower, and less safe (as errors that should have been caught at compile time will be discovered during execution).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.