Interface Mapping

An Interface is a simple contract. When you mark a type as implementing an Interface you agree to provide the methods and events that Interface defines.  A key to that contract is those members are always accessible via the a cast to the Interface, even if they are not accessible in the implementing class.

Fro example, let’s say you have an Interface:

Interface IFoo
    Sub Bar()
End Interface

A type could implement that such as :

Class MyType : Implements IFoo

     Private Sub Bar() Implements IFoo.Bar
     End Sub
End Class

Now note, that even though the interface implementation is marked as private, code from outside the class can still call into that method via the Interface mapping.  Without the Interface mapping they could not. 

So far we have just looked at the basics, common to both C# and Vb.NET, but C# does not use declarative mapping like VB.NET does.  The declarative mapping, helps formalize the interface contract in a flexible and robust manner.

Flexibility is gained from being able to map by signature, not reliant on name.  So code the above implementation could also have been written as :

    Public Sub DoIt() Implements IFoo.Bar

And as the signatures match that is a valid interface mapping, the contract is preserved.

Now when you consider your code in it’s environs, not in isolation, you need to also consider the “what-if’s”, the possibility of change.  At one side you have the Interface (which ideally you would hope won’t change, but it might) and on the other side the requirements of the calling code, which might be using your public methods or might be accessing via the Interface.  So the robustness of your code depends on how well it can implement change as required by surrounding requirements.

So let’s consider a simple change, the calling code requirement becomes that the method should be named DoThat instead of DoIt.  In Vb.NET, not a huge problem, you just modify the DoIt to DoThat.  Obviously all calling code will need to be modified too, but the change was required by the calling code.  The change inside your class can be atomic. (it might not be atomic if you call the method elsewhere in your class, as then your class’s code also becomes the calling code)

Now let’s consider the interface changing.  Say Bar became Stick.  To make that change in your class, you simple update the Implements declaration to Implements IFoo.Stick.   The change is atomic.

Okay so let’s look at how C# deals with this, and hopefully you will start to see the benefits of declarative interface mapping.

In C# you have two approaches you can take.  One is to use implicit mapping, the other is to use explicit mapping. 

Implicit mapping is fraught with potential to break.  It works on matching signature and name. Taking for example. The IFoo.Bar changing to IFoo.Stick.  If you had both void Bar(){…} and void Stick(){…} in your class then suddenly, the code would be pointing to a different method than intended.  The contract has shifted.

So rather than have code subject to naming change issues or naming conflicts, a common approach is to use explicit implementation.  With explicit implementation, the method would become:  void IFoo.Bar() { … }  The problem then becomes that you cannot access that implementation even from inside your class without first casting to the interface.  Code inside the IFoo.Bar method can however call into your class’s code, so the common approach taken is to delegate out to an accessible method rather than have the accessible method call into the interface implementation.  So you might have:
void IFoo.Bar() {Bar()}
public void Bar() { … }

This pattern allows name changes in the Interface to be atomic, but name changes in your own class now cannot be as the coupling requires delegation via the method name.

Now at this point some of you are probably saying “yeh sure, but what about when the signature needs to be changed”.  Well if you look at it, I think you’ll find that the VB code can be more atomic in every case, whereas the C# code faces a different set of issues depending on whether implicit or explicit interfaces were used.

Apart from the elegance and robustness that declarative interface mapping provides, it also provides greater functionality such as allowing multiple methods to be mapped to the one method, and it provides a clear indication of the interface and the mapping.  That is, when you read the code, the interface definition is clear form the implementation.
Compared to C#, where implicit interfaces are not clear. You need to first ensure you know the interface exact signatures  and scan the entire code to ensure that explicit mapping isn’t used. Only then can you jump to the interface implementation.  Or explicit mapping where you often have to look at the explicit interface implementation and then read what method it delegates out to (not absolutely necessary, but is the usual pattern). This later pattern means it may not be obvious when editing a particular method that is being called indirectly for the interface implementation.

To sum up, the CLR provides for true interface mapping.  VB.NET provides this via clear explicit declarative mapping, in a robust and flexible manner.
C# also uses the same CLR provided mapping, but does not actually implement that to the developer in it’s fullness, rather the developer is forced to choose between explicit interfaces (which often means extra stubs in your code calling out to the actual implementation, and is only callable via a cast to the interface even from within your own class) or implicit interfaces which are fraught with dangers and lack any indication of the actual contract.

The benefits of declarative mapping are that code becomes easier to maintain, is more explicit in nature hence easier to read, and is more flexible and robust.  Without doubt, the VB.NET implementation is more elegant than the C#, and more suited to the future as we move more and more into the world of declarative programming. 

Congratulations to the VB.ENT architects on this one.  Job well done ! Although admittedly they just implemented the CLR capabilities in its fullness, whereas C# didn’t, or did so in a very ugly way