none
Switch - object.GetType() Not Working As Expected RRS feed

  • Question

  • I have a variable that has an unknown type until an object is assigned. It can be an object[], string, byte, etc. I tried doing this:

    switch (true)
    {
      case p.Value.GetType() == typeof(object[]):
      break;
      case .Value.GetType() == typeof(byte):
    }

    That always worked, in a similar fashion, in VB. But I get the following error:

    A constant value is expected

    Any ideas?


    Tuesday, December 4, 2012 7:17 PM

Answers

  • "That seems like a huge flaw in C#. Using Selects like this in VB makes code so much cleaner and easier than using tons of nested if/elses."

    That's a matter of opinion.

    Also they wouldn't need to be nested; they'd just be sequential.

    You can also implement it as a dictionary:

    Dictionary<Type, string> lookup = new Dictionary<Type, string>()
    {
        {typeof(int), "Integer"},
        {typeof(object[]), "array"}
    };
    
    object obj = null;
    
    string value = lookup[obj.GetType()];


    If you need it to not resolve to a value, but actually execute code you can use a "Dictionary<Type, Action>" instead.

    Also note that it's generally bad practice to be switching on the type of an object.  It's an indication that you should probably change the design elsewhere to be polymorphic, and have all of the objects implement an interface of some sort that exposes the behavior you need.

    If you *really* have your heart set on using a switch, you can always switch on type name instead of type:

    switch (obj.GetType().Name)
    {
        case ("System.Int"):
            break;
        case ("System.String"):
            break;
    }

    • Proposed as answer by JMCF125 Tuesday, December 4, 2012 8:05 PM
    • Edited by servy42 Tuesday, December 4, 2012 8:05 PM
    • Marked as answer by Lisa ZhuModerator Thursday, December 13, 2012 8:05 AM
    Tuesday, December 4, 2012 8:03 PM

All replies

  • Yes, that is illegal in C#.

    What are you trying to achieve?


    "Premature optimization is the root of all evil." - Knuth

    If I provoked thought, please click the green arrow

    If I provoked Aha! please click Propose as Answer

    Tuesday, December 4, 2012 7:21 PM
  • You may use if statements. And what do you mean with "switch(true)"? You have to choose between different values a variable might hold. the variable is between parantheses, following "switch" and the possible values are after "case".

    Here you go (with if statements, of course):

    if(p.Value.GetType() == typeof(object[]))
    {
        // do something
    }
    else if(p.Value.GetType() == typeof(byte))
    {
        // do something else
    }

    There's no way you can do this with a switch statement. I didn't even know it was possible on VB.


    "Penso, logo existo" - René Descartes
    "A produção de muitas coisas úteis resulta em muitas pessoas inúteis" - Karl Marx
    "Vive como se fosses morrer amanhã, aprende como se fosses viver para sempre" - Mahatma Gandhi

    João Miguel

    • Proposed as answer by JMCF125 Tuesday, December 4, 2012 8:05 PM
    Tuesday, December 4, 2012 7:27 PM
  • Yes, that is illegal in C#.

    What are you trying to achieve?


    "Premature optimization is the root of all evil." - Knuth

    If I provoked thought, please click the green arrow

    If I provoked Aha! please click Propose as Answer

    I'm trying to determine what type the object is without doing a ton of if/else statements

    Tuesday, December 4, 2012 7:33 PM
  • You may use if statements. And what do you mean with "switch(true)"? You have to choose between different values a variable might hold. the variable is between parantheses, following "switch" and the possible values are after "case".

    Here you go (with if statements, of course):

    if(p.Value.GetType() == typeof(object[]))
    {
        // do something
    }
    else if(p.Value.GetType() == typeof(byte))
    {
        // do something else
    }

    There's no way you can do this with a switch statement. I didn't even know it was possible on VB.


    "Penso, logo existo" - René Descartes
    "A produção de muitas coisas úteis resulta em muitas pessoas inúteis" - Karl Marx
    "Vive como se fosses morrer amanhã, aprende como se fosses viver para sempre" - Mahatma Gandhi

    João Miguel

    That seems like a huge flaw in C#. Using Selects like this in VB makes code so much cleaner and easier than using tons of nested if/elses.
    Tuesday, December 4, 2012 7:34 PM
  • Well, that's how it works. How would you do it? Your OP shows "switch(true)". Why use switch then? Those are if statements. Where's the flaw? In writing "if" and "else"? While using single statements in an if statement you may omit the parantheses. The amount of code is the same.

    "Penso, logo existo" - René Descartes
    "A produção de muitas coisas úteis resulta em muitas pessoas inúteis" - Karl Marx
    "Vive como se fosses morrer amanhã, aprende como se fosses viver para sempre" - Mahatma Gandhi

    João Miguel

    Tuesday, December 4, 2012 7:59 PM
  • "That seems like a huge flaw in C#. Using Selects like this in VB makes code so much cleaner and easier than using tons of nested if/elses."

    That's a matter of opinion.

    Also they wouldn't need to be nested; they'd just be sequential.

    You can also implement it as a dictionary:

    Dictionary<Type, string> lookup = new Dictionary<Type, string>()
    {
        {typeof(int), "Integer"},
        {typeof(object[]), "array"}
    };
    
    object obj = null;
    
    string value = lookup[obj.GetType()];


    If you need it to not resolve to a value, but actually execute code you can use a "Dictionary<Type, Action>" instead.

    Also note that it's generally bad practice to be switching on the type of an object.  It's an indication that you should probably change the design elsewhere to be polymorphic, and have all of the objects implement an interface of some sort that exposes the behavior you need.

    If you *really* have your heart set on using a switch, you can always switch on type name instead of type:

    switch (obj.GetType().Name)
    {
        case ("System.Int"):
            break;
        case ("System.String"):
            break;
    }

    • Proposed as answer by JMCF125 Tuesday, December 4, 2012 8:05 PM
    • Edited by servy42 Tuesday, December 4, 2012 8:05 PM
    • Marked as answer by Lisa ZhuModerator Thursday, December 13, 2012 8:05 AM
    Tuesday, December 4, 2012 8:03 PM
  • There is several ways to resolve this problem. If-else statements are one, or you can use some other type property to create switch statement check. But what I've used is create a dictionary of supported types and operation per type; then if new type is needed you just to add it and what to do to the dictionary and no other change is required.

    For example

    class Program { static void Main(string[] args) { Dictionary<Type, Action> supportedTypes = new Dictionary<Type, Action>() { { typeof(string), new Action(() => Console.WriteLine("String action...")) }, { typeof(int), new Action(() => Console.WriteLine("Int32 action...")) }, { typeof(byte), new Action(() => Console.WriteLine("Byte action...")) } }; object value = 345; CheckType(value, supportedTypes); value = "foo"; CheckType(value, supportedTypes); Console.ReadKey(); } static void CheckType(object value, Dictionary<Type, Action> supported) {

    Action action;

    if (supported.TryGetValue(value.GetType(), out action)) action.Invoke(); } }


    • Edited by MasaSam Tuesday, December 4, 2012 8:29 PM
    Tuesday, December 4, 2012 8:12 PM
  • Masa, the entire purpose of using a Dictionary is specifically so that you *don't* need to iterate all of the keys to get to the corresponding value.  You can have O(1) search speed in the average case.

    The entire body of your `CheckType` method can just be:

    Action action;
    if (supported.TryGetValue(key.GetType(), out action))
        action();

    or, if you know it will always exist, you can do:

    supported[key.GetType()]();

    Tuesday, December 4, 2012 8:25 PM
  • Good point, that's true. I tried the similar solution with list and output parameter and I just copied the sample from it without thinking. You don't need to iterate the keys, but still you need the key check unless, you know that the type really is in dictionary.


    • Edited by MasaSam Tuesday, December 4, 2012 8:39 PM
    Tuesday, December 4, 2012 8:35 PM