Velvet Star Monitor

Standout celebrity highlights with iconic style.

general

C# switch on type [duplicate]

Writer Olivia Zamora

Possible Duplicate:
C# - Is there a better alternative than this to 'switch on type'?

C# doesn't support switching on the type of an object.
What is the best pattern of simulating this:

switch (typeof(MyObj)) case Type1: case Type2: case Type3:
10

5 Answers

See another answer; 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.

7

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:

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.

13

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));
}

I have used this form of switch-case on rare occasion. Even then I have found another way to do what I wanted. If you find that this is the only way to accomplish what you need, I would recommend @Mark H's solution.

If this is intended to be a sort of factory creation decision process, there are better ways to do it. Otherwise, I really can't see why you want to use the switch on a type.

Here is a little example expanding on Mark's solution. I think it is a great way to work with types:

Dictionary<Type, Action> typeTests;
public ClassCtor()
{ typeTests = new Dictionary<Type, Action> (); typeTests[typeof(int)] = () => DoIntegerStuff(); typeTests[typeof(string)] = () => DoStringStuff(); typeTests[typeof(bool)] = () => DoBooleanStuff();
}
private void DoBooleanStuff()
{ //do stuff
}
private void DoStringStuff()
{ //do stuff
}
private void DoIntegerStuff()
{ //do stuff
}
public Action CheckTypeAction(Type TypeToTest)
{ if (typeTests.Keys.Contains(TypeToTest)) return typeTests[TypeToTest]; return null; // or some other Action delegate
}
0

I did it one time with a workaround, hope it helps.

string fullName = typeof(MyObj).FullName;
switch (fullName)
{ case "fullName1": case "fullName2": case "fullName3":
}
9