39

I'm trying to create a switch statement using the char index of a string and an Enum using this wrapper to get the value of the selected enum from a Description. It pretty much allows you to store a string to an enum value.

Here is my if statement:

if (msgComingFromFoo[1] == Convert.ToChar(Message.Code.FOO_TRIGGER_SIGNAL.EnumDescriptionToString()))
{
    //foo
}

and here is my switch statement:

switch (msgComingFromFoo[1])
{
    case Convert.ToChar(Message.Code.FOO_TRIGGER_SIGNAL.EnumDescriptionToString()):
        break;
}

Why is it accepting the if statement and not the switch? I tried converting it to a char since I'm selecting an index from a string, but unfortunately it didn't work.

Update:

Here is the Message.Code Enum

public class Message
{
    public enum Code
    {
        [Description("A")]
        FOO_TRIGGER_SIGNAL
    }
}

As you can see, I need the Description assigned to the enum not the enum value that is 0. Using Message.Code.FOO_TRIGGER_SIGNAL.EnumDescriptionToString() from the mentioned wrapper returns A not 0


Error:

A Constant Value Is Expected

Community
  • 1
  • 1
traveler3468
  • 1,557
  • 2
  • 15
  • 28

4 Answers4

54

You cannot have expressions in the case (prior to C# 7), but you can in the switch, so this will work:

switch (ConvertToMessageCode(msgComingFromFoo[1]))
{
    case Message.Code.FOO_TRIGGER_SIGNAL:
        break;
}

Where you will need to write ConvertToMessageCode to do the necessary conversion to the Message.Code enum. ConvertToMessageCode just abstracts the conversion details, you may find you do not need a separate method, but can make do with inline code in the switch statement, e.g., a cast.

Peter Sobhi
  • 2,542
  • 2
  • 22
  • 28
Polyfun
  • 9,479
  • 4
  • 31
  • 39
  • 6
    You [can have expressions in the case in C# 7](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/when#when-in-a-switch-statement) - however I agree that the suggestion in this answer is better design. – BlueRaja - Danny Pflughoeft Jul 31 '18 at 15:54
  • 7
    The historical reason for this is that original concept of the `switch` statement in K&R C was to be the high-level expression of a [Jump Table](https://en.wikipedia.org/wiki/Branch_table). – T.E.D. Jul 31 '18 at 19:03
27

A case in a switch statement must refer to a constant value. You cannot evaluate an expression in a case.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
6

This really is not a good answer as it serves only as elaboration on previous answers. Don't accept it (please also don't upvote above any reasonable answer). I'm writing it as an answer only since a comment won't fit this explanation.


You tried:

switch (msgComingFromFoo[1])
{
    case Convert.ToChar(Message.Code.FOO_TRIGGER_SIGNAL.EnumDescriptionToString()):
        break;
}

This doesn't work since the case is not constant. As suggested, the best way forward is to convert the msgComingFromFoo[1] string back to an enum value so you can switch over the enum and use the enum constants in the switch cases.

If that is somehow not possible, you can always switch over string constants. However, this is error prone and defeats the purpose of using enums in the first place..

switch (msgComingFromFoo[1])
{
    case "A":
        break;
}

Another remark: remember that arrays are zero-indexed. You're currently switching over the second element, not the first. Use msgComingFromFoo[0] for the first element.

Jochem Kuijpers
  • 1,770
  • 3
  • 17
  • 34
5

To add to @code-apprentice 's answer.

If you're finding the if statement is becoming too long or has multiple conditions within if else's. You can look at refactoring the code and encapsulating your logic into an object and using the visitor pattern to control the work to be done.

Something like:

public interface IMessageLogic 
{
   void ProcessMessage()
}

public class TriggerSignal : IMessageLogic 
{
   public void ProcessMessage() 
   {
       // Do trigger stuff
   }
}

public class FooMessage : IMessageLogic 
{
   public void ProcessMessage() 
   {
       // Do foo stuff
   }
}

public class MessageHandler
{
    public void HandleMessage(IMessageLogic messageLogic)
    {
        messageLogic.ProcessMessage();
    }
}

public static void Main()
{
    IMessageLogic messageLogic = GetMessage();
    var handler = new MessageHandler();

    handler.HandleMessage(messageLogic);
 }

Visitor Pattern

Victor Procure
  • 886
  • 1
  • 6
  • 17