Thursday, March 16, 2006

.NET Explicit Interface Implementations

As most .NET developers are well aware of, .NET explicit interface implementations (when the interface name prepends the method name) are a mechanism to avoid naming collisions for interfaces with equal method signatures. The caller then has to cast to whatever interface he intends to refer to, e.g.

public interface ITest1 {
    void Test();
}

public interface ITest2 {
    void Test();
}

public class TestImpl : ITest1, ITest2 {
    void ITest1.Test() {
    }
    void ITest2.Test() {
    }
}

TestImpl test = new TestImpl();
((ITest1)test).Test();
((ITest2)test).Test();


Notice that there are no access modifiers on the method implementations, which forces the caller to cast to which interface he refers to - only then the method implementation becomes accessible.

But there is more to that. This mechanism also allows you to prefer one implementation over the other, e.g.

public class TestImpl : ITest1, ITest2 {
    public void Test() {
    }
    void ITest2.Test() {
    }
}


Now the first method implementation will be invoked on references to TestImpl and ITest1, the second one only on references to ITest2.

.NET uses a similar approach on some framework components, e.g. System.Data.SqlClient.SqlDataAdapter, which implements System.Data.IDbDataAdapter. Part of IDbDataAdapter is the following property declaration:

IDbCommand SelectCommand {
    get;
    set;
}


... where, as expected, SqlCommand implements IDbCommand. But all that can be found on SqlDataAdapter's public members is:

public SqlCommand SelectCommand {
    get;
    set;
}


SqlDataAdapter's IDbDataAdapter.SelectCommand implementation has been hidden on references to SqlDataAdapter, and is only accessible after casting it to IDbDataAdapter:

IDbCommand IDbDataAdapter.SelectCommand {
    get {
        return this._selectCommand;
    }
    set {
        this._selectCommand = (SqlCommand)value;
    }
}


Or have a look at System.Collections.Generic.IEnumerable<T>:

public interface IEnumerable<T> : IEnumerable {
    IEnumerator<T> GetEnumerator();
}

public interface IEnumerable {
    IEnumerator GetEnumerator();
}


Now this seemed like a puzzler to me at first sight. Two methods with the same signature, only differing in their return value? On an implementation level, this is forbidden. But when inheriting from a second interface, the class will simply have to implement one of the methods "explicitly" (means declaring which implementation belongs to which interface).

Looking at .NET's System.Collections.List<T> code (using Lutz Roeder's Reflector), there are even three versions of GetEnumerator(): one for IEnumerator<T>, one for IEnumerator (both explicit interface implementations), and finally a third public implementation:

IEnumerator<T> IEnumerable<T>.GetEnumerator() {
    return new List<T>.Enumerator(this);
}

IEnumerator IEnumerable.GetEnumerator() {
    return new List<T>.Enumerator(this);
}

public List<T>.Enumerator GetEnumerator() {
    return new List<T>.Enumerator(this);
}