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: 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: This got fixed in C# 7.0 with pattern matching
switch (MyObj) { case Type1 t1: case Type2 t2: case Type3 t3: } 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.
switch-case syntax gets. This can lull the programmer into overusing this switch- look-alike class thinking that it gets the same advantages. This looks like a glamorous wrapper for a more expensive if-then-with-lambdas.ToString seems like a bad plan - as renaming types using Visual Studio will break this. Why not typeOf(Type1).Type instance? To have something like switch (typeInstance) { case int: { ... } }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.
if(@switch.ContainsKey(typeof(MyType))) @switch[typeof(MyType)](); typeof(object) != typeof(MyType) even though MyType is a subclass of object.IsAssignableFrom will have to be used to make the comparison. This answer supports sub-types but its ussage is a little verboseAction action; if(@switch.TryGetValue(typeof(Type1), out action) action(); instead of searching twice.. (contains & indexers)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 } I did it one time with a workaround, hope it helps.
string fullName = typeof(MyObj).FullName; switch (fullName) { case "fullName1": case "fullName2": case "fullName3": } case nameof(MyClass): break; so that it is more refactorable