Coder Perfect

Type [duplicate] in C# switch

Problem

C# does not allow you to change the type of an object. What is the most effective method of imitating this:

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

Asked by Adam

Solution #1

This feature is now available in C#, as mentioned in another answer.

Normally, I utilize a type and delegate dictionary.

var @switch = new Dictionary<Type, Action> {
    { typeof(Type1), () => ... },
    { typeof(Type2), () => ... },
    { typeof(Type3), () => ... },
};

@switch[typeof(MyType)]();

You can’t fall through cases, continue, or do anything else, thus it’s a little less versatile. But I don’t do it very often anyway.

Answered by 6 revs, 6 users 62%

Solution #2

Update: C# 7.0 has a pattern matching feature that fixes this issue.

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

Old answer:

It’s a flaw in Cgame, #’s and there’s no silver bullet yet.

You should look up the ‘visitor pattern’ on the internet; it may be a little technical for you, but it is still something you should be aware of.

Here’s another way to look at it, this time with Linq: http://community.bartdesmet.net/blogs/bart/archive/2008/03/30/a-functional-c-type-switch.aspx

Otherwise, anything along these lines would be beneficial.

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

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

etc.

Answered by gjvdkamp

Solution #3

This question has a straightforward answer that uses a type dictionary to look up a lambda function. Here’s an example of how it could be put to use:

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

In terms of pattern matching (both types and run-time checked criteria), there is also a generalized solution to this problem:

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

Answered by cdiggins

Solution #4

I’ve only used this type of switch-case a few times. Even then, I found a different way to accomplish my goals. I would recommend @Mark H’s solution if you find that this is the only method to get what you need.

There are other ways to do this if this is supposed to be a factory creation choice process. Otherwise, I’m not sure why you’d want to utilize the type switch.

Here’s an example that builds on Mark’s solution. It’s an excellent method to work with types, in my opinion:

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
}

Answered by IAbstract

Solution #5

I did it with a workaround once, and I hope it helps.

string fullName = typeof(MyObj).FullName;

switch (fullName)
{
    case "fullName1":
    case "fullName2":
    case "fullName3":
}

Answered by Ghyath Serhal

Post is based on https://stackoverflow.com/questions/4478464/c-sharp-switch-on-type