Search code examples
c#c++genericscode-reusetemplate-mixins

How do people get mixin-style re-use in C#?


I come from a C++ background where I can use template mixins to write code that refers to FinalClass which is a template parameter that is passed in. This allows reusable functions to be "mixed-in" to any derived class, by simply inheriting from ReusableMixin with a template paramter of MyFinalClass. This all gets inlined into the class so it's as though I just wrote a big class that did everything -- ie very fast! Since mixins can chain, I can mix-in all sorts of behaviour (and state) into one object.

If anyone wants clarification on the technique, please ask. My question is, how can I get reuse like that in C#? Note: C# generics don't allow inheriting from a generic parameter.


Solution

  • In C#, the closest you get to C++ style mixins is adding the mixins as fields of a class and add a bunch of forwarding methods to the class:

    public class MyClass
    {
        private readonly Mixin1 mixin1 = new Mixin1();
        private readonly Mixin2 mixin2 = new Mixin2();
    
        public int Property1
        {
            get { return this.mixin1.Property1; }
            set { this.mixin1.Property1 = value; }
        }
    
        public void Do1()
        {
            this.mixin2.Do2();
        }
    }
    

    This is usually enough, if you only want to import functionality & state of the mixins. A mixin can of course be implemented as you like, complete with (private) fields, properties, methods, etc.

    If your class also needs to express "is-a" relationships with the mixins then you need to do the following:

    interface IMixin1
    {
        int Property1 { get; set; }
    }
    
    interface IMixin2
    {
        void Do2();
    }
    
    class MyClass : IMixin1, IMixin2
    {
        // implementation same as before
    }
    

    (This is also the standard way how multiple inheritance is emulated in C#.)

    Of course, the mixin interfaces as well as the mixin classes can be generics, e.g. with a most-derived class parameter or whatever.