Mixins and Traits in C# 3.0

Hi there!

Since C# 3.0 it’s possible to create extension methods. You can regard an extension method as a method that you can add to a class, without even touching it. This might come in handy when you are using an API and have no direct access to the class code. If you wish to do some very important stuff with a certain class but can’t modify the code; extension methods to the rescue!

Suppose I want all my string to be able to shout. “Hello world” is cool, but “HELLO WORLD” is understood by grandma. So we just create a new ShoutableString object and let that inherit from String. We add the Shout method to the class et voila, we can shout.  You might run into some problems when you have other methods and/or classes that return a regular String. You just cast them et voila, you can shout!

Yeah, no. Extension methods you say?

Have you ever used a Tools.cs class or something? A few static utility methods that just *do* stuff to input and return it? Well, extension methods to the rescue. Suppose I want to make my string shoutable:

All you do is create a static class (e.g. “ExtraStringMethods“) and insert the methods you want there:

static class ExpressionMethods
{
    public static string Shout(this string input)
    {
        return input.ToUpper();
    }
}

Well great you say, another utility class. No, not really. Notice the this string” in the input part of the Shout method. This let’s the compiler know that your string objects now have access to this method, just like it would be any other instance method! At compile-time the compiler translates this code to a call to a static method. However, you don’t really care because it’s just sitting there in your intellisense.

In a class, far far away we want to use this stuff. How?  Simple, just import/use using ExpressionMethods; and you will have the methods at your disposal!

    class Program
    {
        static void Main(string[] args)
        {
            var regular = "hello world";
            var shouted = regular.Shout(); //Shouted now equals "HELLO WORLD"
        }
    }

Yeah sure. Cool. What if I want two objects to use the same mixin? It’s not fair I can only use it one type 😦

Marker interfaces! When you DO have access to the class sources you can do a nifty little thing. Suppose I have a User object somewhere, and some other very important objects.
I want all of these methods to be able to write to the console (e.g. log a message for debugging purposes). Well, give them a mixin! But how?

First we use a marker interface (you have read it, didn’t you?) ILog. This just “tags” our classes as loggers.

 interface ILog {}

Tagging our classes is as simple as this:

    class User : ILog
    {

        //This user should be able to log
    }
    class VeryImportantObject : ILog
    {
        //This object should be able to log as well
    }

Awesome, now we have two classes that implement Ilog, but actually don’t do anything special. Now, back to our extension methods.  How do we create a method that works for both these classes? Simple! Remember the this string from last time? We just put ILog there now.

    static class LoggerMethod
    {
        public static void LogMsg(this ILog obj, string msg)
        {
            Console.WriteLine(msg);
        }
    }

Note that the obj parameter is actually a reference to the object you called the method on. So you have access to it’s public members!

So what can we do now? Well we can log stuff really.

        static void Main(string[] args)
        {
            var u = new User();
            u.LogMsg("User doing some important stuff!");

            var io = new VeryImportantObject();
            io.LogMsg("Very imporant object getting moved around!");
        }

Quick note(s):

I have played around with multiple methods with the same name but in other extension methods. This throws:

Error    1    The call is ambiguous between the following methods or properties: ‘LoggerMethod.LogMsg(Mixins_Extension_Methods.ILog, string)’ and ‘BetterLoggerMethod.LogMsg(ILogBetter, string)’   Program.cs    82    13    Mixins Extension Methods

So be careful when implementing multiple mixins!

Also, you can add state to these mixins as well. That’s why I call them mixins instead of traits. However, I personally find the approach a bit cumbersome.
You can simply add static private properties to your Mixin static class (e.g. LoggerMethod) and create getters and setters for them in that same class.

All source code can ben found on BitBucket!

Have fun!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s