The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 2,419 other followers

.NET: interfaces that inherit from multiple base interfaces

Posted by jpluimers on 2020/12/03

For my link archive:

Q

Recently I found out that C# allows for

An interface can inherit from one or more base interfaces.

For instance, the IScreen in Caliburn.Micro does this in http://caliburnmicro.codeplex.com/SourceControl/latest#src/Caliburn.Micro/IScreen.cs

namespace Caliburn.Micro
{
    public interface IScreen : IHaveDisplayName, IActivate, IDeactivate, 
        IGuardClose, INotifyPropertyChangedEx
    {
    }
}

I get why this is useful, as it implies that a class implementing IScreen also needs to implement the other interfaces.

But I wonder how the C# handles that compiler and run-time wise.

A little background/context of this question:

I come from a background where interfaces define a method-table, and that classes implementing interfaces have both their own method table, and pointers to the method tables of the interfaces they implement.

Sub questions swirling my mind stem from various multiple class inheritance discussions I had with people in the past, of which I think they apply to this case as well:

  • Having an interface be able to inherit from multiple base interfaces, how would the order of methods in that table be?
  • What if those interfaces have common ancestors: would those methods appear multiple times in the table?
  • What if those interfaces have different ancestors, but similar method names?

(I’m using the word methods here, implying that a property defined in an interface will have a get_ or set_ method).

Any insight into this is much appreciated, as well as tips on how to phrase this question better.

First of all, let’s be explicit in saying that “interface inheritance” is not quite the same thing as class-based inheritance (and using the word “inheritance” for both is perhaps misleading).

That’s because interfaces cannot be instantiated on their own, so the compiler/runtime pair does not have to keep track of how to make a virtual call for standalone interface types (e.g. you don’t need to know how to call IEnumerable.GetEnumerator — you just need to know how to call it on a specific type of object). That allows for handling things differently at compile time.

Now I don’t actually know how the compiler implements “interface inheritance”, but here’s how it could be doing it:

Having an interface be able to inherit from multiple base interfaces, how would the order of methods in that table be?

It’s not necessary for the “derived” interface to have a method table that includes the methods from all of its ancestor interfaces because it does not actually implement any of them. It’s enough for each interface type to only have a table of methods it defines itself.

What if those interfaces have common ancestors: would those methods appear multiple times in the table?

Given the answer to the previous question, no. In the end a concrete type will only implement IFoojust once, regardless of how many times IFoo appears in the “hierarchy” of implemented interfaces. Methods defined in IFoo will only appear in IFoo‘s bookkeeping tables.

What if those interfaces have different ancestors, but similar method names?

Again, no problem. You need appropriate syntax to tell the compiler “here’s how to implement IFoo.Frob and here’s IBar.Frob“, but since methods of IFoo and IBar will be mapped in separate tables there are no technical issues.

Of course this leaves the question “how are methods dispatched at runtime?” unanswered. But it’s not that difficult to imagine a possible solution: each concrete type C has pointers to one method table per interface it implements. When it’s time to make a virtual method call the runtime looks at the concrete type, finds the table for the interface whose method is going to be called (the type of the interface is known statically) and makes the call.

A2

I am unable to speak to how the official CLR does it.. but the Rotor distribution aggresively overlays common interface ancestors on top of one another in an objects vtable. It also allocates extra SLOTs into the concrete objects vtable where appropriate thereby reducing the need to jump from concrete type to interface vtable and then to the implementation.. the method offset is calculated at JIT time. If this optimization cannot be performed, then a single method can occupy the vtable more than once.

So the answer is (in regards to Rotor anyway), that it really is an implementation detail and any overlaying/optimizations etc are left completely up to what the compiler decides is best at the time it compiles the type.

–jeroen

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

 
%d bloggers like this: