Mixins, generics and extension methods in C#

Bruce Eckel wrote about the impossibility to implement mixins in Java using generics. This made me think back to my C++ days and if and how this can be done in (future versions of) C#.

Let me first start with a problem statement. Say you want to adorn a class with a timestamp. Meaning when you create an instance of such class, you want to automatically have it stamped with the time of its creation. You want any instance of that to have a read-only Timestamp property of an appropriate type (say System.DateTime in C#).

There are a couple of cases to consider:

  1. You author both the behavior and the classes and just want to save on typing duplicate code.
  2. You want to author timestamp behavior for a library. Consumers of that library can mixin the behavior to classes they author.
  3. You consume existing classes you cannot change and you want to add the timestamp behavior to them.

Let’s start with the most straightforward approach. Just whip up an abstract base class called Timestamped and derive your classes from it.

      public abstract class Timestamped

      {
            private DateTime _timeStamp = DateTime.Now;

            public DateTime Timestamp
            {
                  get { return _timeStamp; }
            }
      }          

      public class TimestampedPerson: Timestamped
      {
            ...
      }

 

Of course, the usual drawbacks apply. The CLR, and thus C#, doesn’t support multiple inheritance, so this precludes you from deriving your class from other base classes. Also it doesn’t work for existing classes.

Say you have an existing Person class:

      public class Person
      {
            private string _name;
            private int _age;

            public Person(string name, int age)
            {
                  _name = name;
                  _age = age;
            }

            public string Name { get { return _name; } }

            public int Age { get { return _age; } }
      }

Since you cannot derive from Timestamped you can add the behavior by deriving from Person.  You might hope to solve this in C# 2.0 once-and-for-all using generics. Just declare the following generic type:

      public class Timestamped<T> : T
      {
            private DateTime _timestamp;

            public Timestamped()
            {
                  _timestamp = DateTime.Now;
            }

            public DateTime Timestamp
            {
                  get
                  {
                        return _timestamp;
                  }
            }
      }

 

So you can now have a Timestamped<Person>. Unfortunately generics in .NET 2.0 do not allow you to derive from a bare type parameter. Also you would run into the problem of how to construct an instance. Person does not have a default constructor and Timestamped<Person> does not have a constructor that takes a string and an int and passes it along to the base class constructor Person(string name, int age). You could add such a constructor to Timestamped<T> but then it would no longer be generic. Even if this would be possible, what if the Person class was sealed? This precludes you from deriving from it.

Note that C++ templates do allow you to derive from the type parameter. C++ does suffer from the constructor problem. Nevertheless this is a widely used approach for mixins.

Extension methods

What about extension methods? In C# 3.0 it will be possible to add methods to existing classes. Olaf Conijn noted that this is similar to mixins. Because there are no extension properties announced as of yet for C# 3.0, I have to use a GetTimestamp method instead of a Timestamp property. So what about:

      namespace Stamp
      {
            public static class TimeStampExtension
            {
                  public static DateTime GetTimestamp(this object o)
                  {
                        return DateTime.Now;
                  }
            }
      }

 

If you now include using Stamp in your code, every object gains the GetTimestamp method. So I could write:

                  Person jan = new Person("Jan", 30); 
                 
Console.WriteLine( jan.GetTimestamp() );

 

But it is also pretty clear that this doesn’t give us what we want. The GetTimestamp method returns the time at which it is called. It has no way of knowing at what time the Person  instance on which it was called was created. The reason is that extension methods cannot add state to an object. So this rules out extension methods for this type of mixin.

I have seen other approaches for mixins in C# using a whole lot of proxy and interception magic, but I think this just looks ugly.

It’s not clear to me if there is more that hasn't been announced for C# 3.0. I hope Microsoft will find a way to make mixins first class citizens in the language.

One thought on “Mixins, generics and extension methods in C#

  1. I think the solution is to use dynamic code gen. I was thinking of doing this to solve a problem with XAML and extending the existing ItemsControls. The solution would have to create a new type using IL.Emit that is based on the current class and takes a Mixin class as a parameter which it uses to reroute the virtual methods and properties. The generated class would be derived from the main class and so compatible with the existing assigned variable.

    I may post a solution to this if I get it working.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *