Saturday, October 18, 2008

Implementing interfaces in VB.Net

In this post I'll talk about VB's explicit interface implementation and how to best exploit the power this brings. I guess that it's a well known fact that interface implementation in VB is explicit but what does that mean really? It simply means that to implement an interface in a class the developer has to explicitly declare what members of the class implements the members of the interface. C# also has the ability to explicitly implement interfaces but it supports implicit interface implementation too which lets you implement an interface by declaring members with the same names and signatures as those of the interface. To implement the IDisposable interface implicitly we'd write the following:

public class Foo : IDisposable
{
    public void Dispose()
    {
        // Implementation here...
    }
}

The developer never tells the compiler that the method named "Dispose" implements the method "Dispose" of the IDisposable interface, the compiler figures this out by comparing the name and the signature of the method. To explicitly implement an interface in C# we'd write the following instead:

public class Foo : IDisposable
{
    void IDisposable.Dispose()
    {
        // Implementation here...
    }
}

In this implementation we explicitly say that the "Dispose" method implements the "Dispose" method of the interface IDisposable, note that there is no scope declared for this method, this is because it's only accessible through the interface. If you held an instance of the class "Foo" you would not be able to invoke the Dispose method without casting the instance to IDisposable.

Foo foo = new Foo();

foo.Dispose(); // will not compile
(foo as IDisposable).Dispose(); // will compile

As seen here this means that a method that implements an interface method must have the same name as the interface method and be public OR have no name at all and be private (explicit implementation). In VB on the other hand where implementation is always explicit we have a lot more freedom regarding naming and scope. For example a method implementing an interface method can have any scope (Private, Protected, Friend or Public) and also any name. Oh, well, any valid name that is.

Public Class Foo
    Implements IDisposable

    Public Sub ThisMethodIsNotNamedDispose() Implements IDisposable.Dispose
        ' Implementation here...
    End Sub

End Class

Now we have a public method called something completely different than "Dispose" but still implementing the "Dispose" method, if you were to cast an instance of the Foo class to the IDisposable interface and call the "Dispose" method on it the method "ThisMethodIsNotNamedDispose" would be invoked. As I said earlier an implementing method can have any scope, the method "ThisMethodIsNotNamedDispose" could just as well have been made private for example and we would end up with a situation very similar to the C# way of explicitly implementing interfaces. One very big difference though is that from within the class Foo you'd be able to call the method "ThisMethodIsNotNamedDispose" even though it's private, in C# however you can never call an explicit member implementation without casting to the interface, not even from within the implementing class itself.

Another cool thing about VB's explicit interface implementation is that a single method or property can implement methods or properties from multiple interfaces at the same time.

Public Class Foo
    Implements ICollection, ICountable

    '...

    Public ReadOnly Property Count() As Integer Implements ICollection.Count, ICountable.Count
        Get
            Return theCount
        End Get
    End Property

    '...

End Class

Public Interface ICountable
    ReadOnly Property Count() As Integer
End Interface

Interface implementation is one of the very few areas where I think VB outshines C# (XML-literals being the other area).

I think that hiding the methods of the interface in the public interface of the class (by explicitly implement the interface in C# and setting a non public scope in VB) is something that should be sparsely used. I use it only when a method makes no sense when the concrete type is known. For example if you create a LinkedList that implements the ICollection(T) interface there is really no need to ever call the "IsReadOnly" property when you know that you're holding a LinkedList that is never read only, this interface property should be hidden from the public interface of the class.

I've used the IDisposable interface as an example here but I would strongly advice against ever hiding the "Dispose" method of this interface in production code.

Field prefixes

The debate on whether to prefix private variables with a leading "_" or "m_" has engaged a lot of people lately since the public release of Style Cop which which enforces the "m_"-prefix (at least that's what I've been told, I haven't had a chance to try the application myself yet).

I think that prefixes are always bad, whether it's an "I" for interface, "C" for class or "m_" for member. I do appreciate the historic reasons for them but there is really no valid reason anymore, we have the "this" and "Me" keywords in C# and VB to differentiate between member variables and local variables or parameters. The only valid reason as I see it is to differentiate between a field and the property that expose that field.

public class Foo
{
    protected string _bar;

    public string Bar
    {
        get { return _bar; }
        set { _bar = value; }
    }
}

You might say that you could just use camelCasing for the field and PascalCasing for the property, but suppose that the class was to be inherited by VB.Net, "bar" would now be ambigous because VB is case insensitive thus the prefix has some validity. However since the introduction of automatic properties I see no reason for the prefix anymore. The only reason would have to do with performance (you could access the field direclty from inside the class rather than through the property) and I'd say that in most cases that's neglectible and I'd go with the increased maintainability the automatic properties gives you. Premature optimization is the root of all evil. Also in the example, if the backing field was just declared as private (as it should) there would be no issue.