2

Just out of curiosity: are calls using the base keyword in C# dynamically bound (i.e. is it a polymorphic call)?

Consider the following example:

public class A
{
    public virtual void WriteSomething() 
    { 
        Console.WriteLine("Hello from A"); 
    }
}

public class B : A
{
    public override void WriteSomething() 
    { 
        base.WriteSomething();
        Console.WriteLine("Hello from B");
    }
}

public class Program
{
    public static void Main()
    {
        A instance = new B();
        instance.WriteSomething();
    }
}

I know that when a client (in this example the Main method) calls instance.WriteSomething, this call is dynamically bound. But what about the base.WriteSomething call in the overridden method in class B? I assume that it is not dynamically bound because the compiler knows the base class at compile time and therefore Dynamic Binding is not necessary - but I couldn't find any documentation on that.

Thanks for your help in advance!

feO2x
  • 5,358
  • 2
  • 37
  • 46
  • What makes you think that `instance.WriteSomething` is dynamically bound? – Enigmativity Nov 05 '15 at 09:45
  • That would be prone to infinite recursion, wouldn't it? If both a base and a derived class implement `f()` and the derived calls `base.f()` and adds something to it, which is a common pattern, `base.f()` would then in fact call the most-derived implementation of `f()` again (or what else would the semantics be? If it always calls the most-derived-but-one implementation, you can construct a similar scenario). – Peter - Reinstate Monica Nov 05 '15 at 09:48
  • @Enigmativity because it's declared virtual? – Peter - Reinstate Monica Nov 05 '15 at 09:49
  • @PeterSchneider: you are right, that would lead to infinite recursion. I hadn't thought that far. – feO2x Nov 05 '15 at 09:57
  • @PeterSchneider - I thought `virtual` was just to enable overriding and that the compiler still hard coded the calls. – Enigmativity Nov 05 '15 at 10:00
  • @Enigmativity The compiler cannot generally know at compile time what (type of) object is behind a reference, so it cannot hard-wire virtual function calls. That's the big difference between oveloaded functions (lookup at compile time depending on the *argument's reference* type) and polymorphic calls to virtual functions (lookup at run time through a table of function pointers which is different for every type and to which each *calling object* (not the reference) keeps a pointer.-- Non-virtual calls, b.c., are hardwired : You'll get the implementation for the type the *reference* indicates. – Peter - Reinstate Monica Nov 05 '15 at 10:43
  • @Enigmativity Of course the compiler at compile time or the JIT at run time could optimize away the virtual function lookup in this specific case because both can prove that no code path ever writes to the reference again after it has been initialized with a B, so that it must be always `B.WriteSomething`. Ah well, I guess in this *specific* case the JIT never kicks in ;-). – Peter - Reinstate Monica Nov 05 '15 at 10:48
  • @PeterSchneider - Ah, your comment 31 seconds ago was what I was thinking. – Enigmativity Nov 05 '15 at 10:49

1 Answers1

1

Well I just had a look at the Intermediate Language and there one can see that the base call is not dynamically bound (the blue rectangle):

enter image description here

feO2x
  • 5,358
  • 2
  • 37
  • 46