C# switch on type

See gjvdkamp's answer below; this feature now exists in C#


I usually use a dictionary of types and delegates.
var @switch = new Dictionary<Type, Action> {
    { typeof(Type1), () => ... },
    { typeof(Type2), () => ... },
    { typeof(Type3), () => ... },
};

@switch[typeof(MyType)]();

It's a little less flexible as you can't fall through cases, continue etc. But I rarely do so anyway.


Update: This got fixed in C# 7.0 with pattern matching

switch (MyObj)
    case Type1 t1: 
    case Type2 t2:
    case Type3 t3:

Old answer:

It is a hole in C#'s game, no silver bullet yet.

You should google on the 'visitor pattern' but it might be a little heavy for you but still something you should know about.

Here's another take on the matter using Linq: http://community.bartdesmet.net/blogs/bart/archive/2008/03/30/a-functional-c-type-switch.aspx

Otherwise something along these lines could help

// nasty..
switch(MyObj.GetType.ToString()){
  case "Type1": etc
}

// clumsy...
if myObj  is Type1 then
if myObj is Type2 then

etc.


There is a simple answer to this question which uses a dictionary of types to look up a lambda function. Here is how it might be used:

var ts = new TypeSwitch()
    .Case((int x) => Console.WriteLine("int"))
    .Case((bool x) => Console.WriteLine("bool"))
    .Case((string x) => Console.WriteLine("string"));

ts.Switch(42);
ts.Switch(false);
ts.Switch("hello");

There is also a generalized solution to this problem in terms of pattern matching (both types and run-time checked conditions):

var getRentPrice = new PatternMatcher<int>()
    .Case<MotorCycle>(bike => 100 + bike.Cylinders * 10) 
    .Case<Bicycle>(30) 
    .Case<Car>(car => car.EngineType == EngineType.Diesel, car => 220 + car.Doors * 20)
    .Case<Car>(car => car.EngineType == EngineType.Gasoline, car => 200 + car.Doors * 20)
    .Default(0);

var vehicles = new object[] {
    new Car { EngineType = EngineType.Diesel, Doors = 2 },
    new Car { EngineType = EngineType.Diesel, Doors = 4 },
    new Car { EngineType = EngineType.Gasoline, Doors = 3 },
    new Car { EngineType = EngineType.Gasoline, Doors = 5 },
    new Bicycle(),
    new MotorCycle { Cylinders = 2 },
    new MotorCycle { Cylinders = 3 },
};

foreach (var v in vehicles)
{
    Console.WriteLine("Vehicle of type {0} costs {1} to rent", v.GetType(), getRentPrice.Match(v));
}