Type (of) Design Challenge

A long time ago, on my first programming job I had a design problem that I couldn’t solve.
This problem haunted me. The reason was that it seemed so simple, and yet I couldn’t find a good solution for it.

Eventually I did a huge refactor, but instead of solving it correctly I simply changed one problem to another.

Recently, years later, in a different company, I came up with that great solution I was after.
So besides telling you I’m thinking about code from years ago way too much, I want to share with you my exciting great solution.

The challenge

Let’s say we have a Car class and we want info about our engine.
We can have a Diesel engine, A V-Type Engine, a Straight engine and so on.

Disclaimer: I don’t really understand anything about car engines

Our challenge is: How to represent our engine type?

Consider that I want my engine type to have functionality.
Example of what EngineType should be able to do:

  • GetHorsePower()
  • GetPrice()
  • GetPriceForUsed(int yearsOld)
  • CalculateAccelerationWithCarWeight(int carWeight)

Option #1: Inheritance

We can have base classes for our engines and the Car will inherit from them. Like this:

Hmmm that sure is interesting but it feels wrong.

What if we want to add GearType and WheelsType? I can’t do multi-inheritance in C#. And even if I could, this design doesn’t feel right. An Engine is part of a car. A car is not a sub-class of an Engine.

This leads us to option #2.

Option #2: Enums

We’ll have an Enum with all our engine types.
And our ICar will have an EngineType property

That’s better. But what about that functionality I wanted like Car.Engine.GetPrice()  or Car.Engine.GetHorsePower().

First thought that comes to mind is extension methods for our enum:

And now MyCar.Engine.GetHorsePower() will work great!

Ok, so this will work but I don’t like it too much. We’ll have helper classes with lots and lots of switch-case statements.
Whenever we add a new engine type, we’ll have to go to each switch-case and add the new engine. What if we forget? Besides, we’re object-oriented and this doesn’t feel very object orienty…
Hmm let’s try solving with classes..

Option #3: Classes

Should be pretty straightforward, right?

This looks much better. But still, there are a few things I don’t like

  • Why do I need to create a new instance of V8Engine? It’s always the same… Looks wasteful
  • How do I compare two engines? I’ll need something like
    if (engine1.GetType() == engine2.GetType())
    That’s weird, right?

What if I turn all my classes to Singletons??

I like this more. To compare two engines I can do use a simple == operator since there’s just the one instance.

What I still don’t like is that anyone can inherit from IEngine and create their own custom EngineType.

If you know Java, you might be thinking “In Java, I just extend my enum. C# sucks.”
And truth be told, in Java this is really simple to solve

Isn’t it cool? I think so.

You can’t do that in C#. Or can you?

Option #4: Java-like enums in C#

With a little nested class magic you can achieve just that. Here’s how:

Or alternatively:

The constructor should be private so that no one out of this class could create a new EngineType.

So this is it. This solves my Type design problem, for me at least. If you have other ideas on ways to implement this, I’ll love to hear them.

Some more issues about this approach:

  • By using partial class you can place your nested classes in different files
  • Switch-case won’t work like in a regular enum and there’s no way around it
  • Another trick, which I didn’t show is to use a regular enum with attributes
    http://stackoverflow.com/questions/469287/c-sharp-vs-java-enum-for-those-new-to-c/4778347#4778347
    For example
    And with extension methods we can get access to the attribute values.

Leave a Reply