The Life of a Programmer

Adding proxies to C#: A simple proposition

C# prefers composition to inheritance yet lacks any concise composition syntax. This is unfortunate. While I have nothing against composition, I really don’t like the redundancy of manually forwarding methods. Here I propose a simple syntax that would make composition simple and painless.

The example

Composition in C# currently looks like the below code. If you do a lot of Java you’ll also be familiar with this.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class Composed : ISomething {
    SomethingImpl impl;

    //manual kludge
    public void FirstMethod( int a, int b ) {
        impl.FirstMethod( a, b );
    }

    public string SecondMethod( float c, Type[] d ) {
        return impl.SecondMethod( c, d );
    }
}

It’s a bit weird that neither C# nor Java have a succinct way to compose classes. Most other common languages do. In C++ this can be handled with multiple inheritance, though the syntax is kind of odd. Python also has multiple inheritance. Ruby is known for its mixins, which also appear in PHP now. Several languages have explicit traits system. Perl seems to have traits, mixins, and multiple inheritance.

I propose the below syntax to make this much nicer.

1
2
3
4
5
public class Composed : ISomething {
    SomethingImpl impl;

    proxy impl as ISomething;
}

In contrast to the murky manual proxying this explicit proxy code expresses clearly what I intend. I want the entire ISomething interface from SomethingImpl to be exposed in my Composed class. This is equivalent to manually forwarding all of the individual interface methods with the exact same name and parameters.

This avoids potential defects with mistyping the names, types or parameters. Should the interface change I can also leave my code exactly as is. It automatically changes along with the interface. These are both great points for code maintenance.

Selection of proxy

The as ISomething is an important part of the syntax. Typically our implementations need to have far more public methods than what the interface provides. Otherwise it may not be very usable form the Composition class itself. A syntax without the as part would thus expose too many details.

1
2
3
4
5
6
public class PoorlyComposed : ISomething {
    SomethingImpl impl;

    //would include all public methods in SomethingImpl
    proxy impl;
}

I can nonetheless see value in proxying all public methods, so perhaps this syntax should also be allowed. But for the most part you’d likely only want to expose a limited subset. In this case you want something to implement the ISomething interface and nothing more.

We might want even more fine-grained control over what happens. Let’s also allow for proxying individual functions.

1
2
3
4
5
6
7
public class PiecewiseComposed : ISomething {
    SomethingImpl impl;

    proxy impl.FirstMethod;

    public string SecondMethod( float c, Type[] d ) { ... }
}

Here we proxy the FirstMethod and manually implement SecondMethod.

We might want one additional feature dealing with larger interfaces. Suppose you wish to proxy almost all of the interface, but override just one or two methods. This could be allowed using the current override syntax.

1
2
3
4
5
6
7
public class MinimallyComposed : IComplex {
    ComplexImpl impl;

    proxy impl as IComplex;

    public override int ComplexMethod( int a ) { ... }
}

Implementation

This feature should be relatively easy to implement as it requires no additional runtime support. The compiler can quite simply translate these proxy statements into the normal proxying code. The definition of the interface and the implementation are already required, so it doesn’t introduce any new dependencies. Nor does it introduce any kind of new typing rules or semantics.

I would love to see this added to the language. It significantly reduces redundancy in composing classes, improves code clarity, and makes maintenance easier.

If like to explore languages and compilers then follow me on Twitter. I always have more ideas and things to uncover. If there’s something special you’d like to hear about, or want to arrange a presentation feel free to contact me.

Please join me on Discord to discuss, or ping me on Mastadon.

Adding proxies to C#: A simple proposition

A Harmony of People. Code That Runs the World. And the Individual Behind the Keyboard.

Mailing List

Signup to my mailing list to get notified of each article I publish.

Recent Posts