tags:

views:

727

answers:

8

I have defined a C# enum as

   public enum ORDER
    {
        ...
        unknown,
        partial01,
        partial12,
        partial23,
    }

and can use its value as a string as in:

            string ss = ORDER.partial01.ToString();

However when I try to use it in a case statement it fails to compile:

            string value = ...
            switch (value)
            {
                case null:
                    break;
                case "s":
                    // OK
                    break;
                case ORDER.partial01.ToString():
                    // compiler throws "a constant value is expected"

                    break;
              ...

I thought enums were constants. How do I get around this?

(I cannot parse the value into an enum as some of the values are outside the range)

+3  A: 

The enum is a constant, but the result of .ToString() is not. As far as the compiler is concerned, it is a dynamic value. You probably need to convert your switch case into a series of if/else statements

Joel Martinez
+5  A: 

Convert the string in your switch to an enum value.

(ORDER)Enum.Parse(typeof(ORDER), value, true);
sipwiz
That won't handle the null comparison, but that edge case could be handled outside the case statement.
John Fisher
string value = null; //"partial01";ORDER? order = value == null? null : (ORDER?)Enum.Parse(typeof(ORDER), value, true);
Richard Hein
+1  A: 

Enum values are constants, but you're trying to use the results of a method (ORDER.partial01.ToString()), not a constant.

The best option, in my opinion, would be to just switch this around to using if/else if/else statements, instead of a switch. This would allow you to use the logic you are desiring.

Alternatively, if you switch your string into the enum value, you can switch on the enum values directly. You cannot switch on the enum + null + other strings, though, in one switch.

Reed Copsey
You can switch on null if you use ORDER? ... not strings, however.
Richard Hein
+2  A: 

Couldn't you just instead say

case "partial01":

?

eWolf
Then you'd be hard-coding and duplicating the values in the Enum. That could get ugly pretty fast.
Gregg Cleland
A: 

enums are constant but ToString() is a function returning a value. based on the instance of the enum object it's being called on.

That is the two statements:

ORDER.partial01.ToString()
ORDER.partial02.ToString()

calls the same function but returns two different values, so the call to the function .ToString() is in it self not a constant value.

Rune FS
A: 

This is not a static value as far as the compiler is concerned, since it is a function call:

ORDER.partial01.ToString()

Therefore, you can't use it as a comparison in a case statement. However, you can simply do this:

case "partial01"

That would work, since the enum value and the string are identical.

John Fisher
+2  A: 

As an alternative to using if .. else, you could convert your string to an enum first. It would probably not make much sense if the number of options is small though:

if (Enum.IsDefined(typeof(ORDER), value))
{
    switch ((ORDER)Enum.Parse(typeof(ORDER), value)
    {
        case ORDER.partial01:
            // ... 
            break;
        case ORDER.partial12:
            // etc
    }
}
else
{
    // Handle values not in enum here if needed
}

*sigh* if only there was a built-in T Enum.Parse<T>(string value), and a TryParse version :)

Thorarin
A: 

You designed this as an enum for a reason, but you're not really making use of it as an enum. Why are you taking the enum value and converting it to a string to then use in the switch instead of simply using the enum?

You said that you can't parse this in to an enum because some of the values are outside the enum range. The question to ask then is, "Why?" What is the point of having the enum if you are allowing values that aren't defined? What is it that you want to happen when you get a value that isn't defined? If it's the same thing for any undefined value, then you can use the default case. If it's not, then you can include additional cases that match the numeric representation.

If you really do get strings back, then you probably don't want to use an enum. Instead you want to create a public static class containing public string constants, which you can then use in your switch. The trick here is that the evaluation will be done in a case sensitive manner.

public static class Order
{
   public const string Unknown = "Unknown";
   public const string Partial01 = "Partial01";
   public const string Partial12 = "Partial12";
   public const string Partial23 = "Partial23";
}

string value = Order.Partial01
switch (value)
{
   case Order.Partial01:
      break;

    default:
       // Code you might want to run in case you are
       // given a value that doesn't match.
       break;
}

(You might also want to clean up your casing.)

Scott Dorman
there are times when only the enum values are examined and other times when a wider range of values are involved. I agree it's probably a messy design and it may go away later.
peter.murray.rust
@peter.murray.rust: What type of value do you actually get back? Do you always get the value as a string or is it numeric? If it's numeric, keep the enum, switch on the value **as an enum** and have either a default case or other labeled cases that match the "extra" values to do the appropriate work. If it's string, then go with the approach I showed and have a static class that holds the string representations. You can still add other labeled cases that match the "extra" values.Bottom line, an enum is really only useful if you want to give numeric values "friendly" or meaningful names.
Scott Dorman