Interface implementation delegation

Topics: C# Language Design
May 12, 2014 at 2:50 AM
I've searched list of discussions and I'm quite surprised that there is no discussion about that, so I'm going to start one.

There was an idea posted by Simon Ferquel about Interface Implementation Delegation feature. I couldn't find a blogpost about it, but there is a word document. I've uploaded it to onedrive: http://1drv.ms/1j9sYcr.

There is also a blogpost by Matthieu MEZIL with a rewriter which implements that feature: http://msmvps.com/blogs/matthieu/archive/2014/02/26/interface-implementation-delegation.aspx

To give a little overview, this feature would be a syntactic sugare to allow delegate interface implementation to a field/property, with additional ability to override some of interface members with custom code:
public class NotifyCollectionWrapper<T> : ICollection<T>(_innerCollection)
{
    ICollection<T> _innerCollection;

    public NotifyCollectionWrapper(ICollection<T> innerCollection){
        _innerCollection = innerCollection;
    }

    void Add(T item)
    {
        _innerCollection.Add(item);
        // raise event
    }
}
Compiler would generate all missing ICollection<T> members following given pattern:
int Contains(T item)
{
    return _innerCollection.Contains(item);
}
Things that should be discussed:
  • should generated code implement interface members implicitly or explicitly?
  • should there be any additional null check before _field.Foo() is called?
  • how does proposed syntax work with primary constructors and calling base class constructors?
May 12, 2014 at 2:56 AM
Edited May 12, 2014 at 2:57 AM
And to start the discussion, here is how I would answer those questions:
  • should generated code implement interface members implicitly or explicitly?
I'd rather do it implicitly. I rarely use explicit interface implementation at all, and think that's not just me. However, no matter which way we'd implement that feature, there is still an ability to override default implementation: just by providing your own one.
  • should there be any additional null check before _field.Foo() is called?
The only reason why it would be useful is to raise different exception than default NullReferenceException. Simon suggested ImplementingMemberNullException:
[Serializable]
public class ImplementingMemberNullException : NullReferenceException
{
    public object Target { get; private set; }
    public string MemberName { get; private set; }

    public ImplementingMemberNullException() { }
    public ImplementingMemberNullException( object target, string memberName ) : base( ExceptionMessageHelper.GenerateMemberIsNullMessage(memberName) ) { 
        Target = target;
        MemberName = memberName;
    }
  protected ImplementingMemberNullException( 
    System.Runtime.Serialization.SerializationInfo info, 
    System.Runtime.Serialization.StreamingContext context ) : base( info, context ) { }
}
but I personally don't like that solution. I think NullReferenceException is something I would expect to get when my field I delegate interface implementation to is null. And no additional null check is required to get that behavior.
  • how does proposed syntax work with primary constructors and calling base class constructors?
I'm not really following the entire primary constructor discussion, so I don't have enough information to answer that question. Anyone with more insights into primary constructors feature can share his thoughts?
May 12, 2014 at 1:51 PM
The proper way to implement such a thing, although C# has unfortunately not generally taken such an approach, would be to have an explicit interface chain to a protected virtual member. Interface implementations should frequently not be public member functions (since the fact that a class implements IFoo.Bar() a certain way does not imply that should expose that method as its own Bar method), but the implementing code should be protected and virtual to allow for proper overriding. The VB.NET approach of directly allowing Protected Overridable Sub IFoo_Moo() Implements IFoo.Moo is semantically-correct, but C# does not at present allow any such thing.
May 14, 2014 at 1:52 AM
For me, the main usage of this feature would be for implementing collection classes. The BCL's design encourages the use of many specialized collection classes like Control.Children, XmlElement.Attributes, Matches.Groups and so on, which is part of what makes LINQ so useful. However, writing a collection class still involves quite a lot of boilerplate code if the base ObjectModel.Collection<T> class doesn't quite match your needs or if you want a value type enumerator. In this case, explicit interface implementations can actually be very useful since you typically don't want your dictionary class inheriting the ICollection<KeyValuePair<TKey, TValue>> methods.

As for the syntax, I'm not too much a fan about cluttering the type definition, especially with primary constructors already adding a lot complexity there. I don't have a good alternative to suggest, though. However, this seems like a good place to reuse the implicit and explicit keywords.

I will also say that the => property/method implementation syntax goes a long way towards lessening this burden.
May 14, 2014 at 3:29 AM
The thing I think is missing from collections is a means of extending interfaces like IEnumerable<T> without breaking existing implementations (have the class loader auto-generate stubs for unimplemented members which would invoke static members designated by intefface member attributes). Imagine how much more performant Linq could be if, e.g. IEnumerator and IEnumerator<T> included aMove` method which chained the following, but which collection enumerators were free to implement better:
static class IEnumeratorClassHelpers<U>
{
    int Move<T>(T it, int distance) where T:IEnumerator<U>
    {
      if (distance < 0) throw new ArgumentException("Basic enumerator does not support negative displacement");
      while(distance > 0 && it.MoveNext())
        distance--;
      return distance;
    }
}
static class IEnumeratorStructHelpers<U>
{
    int Move<T>(ref T it, int distance) where T:IEnumerator<U>
    {
      if (distance < 0) throw new ArgumentException("Basic enumerator does not support negative displacement");
      while(distance > 0 && it.MoveNext())
        distance--;
      return distance;
    }
}
Even adding just that one method to IEnumerator<T> could enormously speed up the performance of many Linq operators on many kinds of collections, and allow things like Append to offer good performance. A default Count implementation could try to move forward 2.1 billion elements, and then observe how many were left to move once the end of the collection was reached; something like an Append-generated composite collection, which combined some collections which supported rapid skipping and some which did not, would be able to skip quickly over the parts of the collection which supported rapid skipping.

I don't know what all would have to happen to allow IEnumerable<T> and IEnumerator<T> to include efficient methods for bulk operations, snapshots, etc. but I would think such things would make Linq vastly more useful.