37

Does anyone know how to get enum values to string?

example:

private static void PullReviews(string action, HttpContext context)
{
    switch (action)
    {
        case ProductReviewType.Good.ToString():
            PullGoodReviews(context);
            break;
        case ProductReviewType.Bad.ToString():
            PullBadReviews(context);
            break;
    }
}

Edit:

When trying to use ToString(); the compiler complains because the case statement is expecting a constant. I also know that ToString() is is striked out with a line in intellisense

3
  • 8
    who the hell voted to close this? and why? Commented Jun 25, 2010 at 18:28
  • Will converting from string to enum work for you? msdn.microsoft.com/en-us/library/essfb559.aspx Commented Jun 25, 2010 at 18:29
  • I'm going the other route. Enum value to a string because I want to compare the incoming action parameter. Commented Jun 25, 2010 at 18:30

6 Answers 6

39

Yes, you can use .ToString() to get a string value for an enum, however you can't use .ToString() in a switch statement. Switch statements need constant expressions, and .ToString() does not evaluate until runtime, so the compiler will throw an error.

To get the behavior you want, with a little change in the approach, you can use enum.Parse() to convert the action string to an enum value, and switch on that enum value instead. As of .NET 4 you can use Enum.TryParse() and do the error checking and handling upfront, rather than in the switch body.

If it were me, I'd parse the string to an enum value and switch on that, rather than switching on the string.

private static void PullReviews(string action, HttpContext context)
{
    ProductReviewType review;

    //there is an optional boolean flag to specify ignore case
    if(!Enum.TryParse(action,out review))
    {
       //throw bad enum parse
    }


    switch (review)
    {
        case ProductReviewType.Good:
            PullGoodReviews(context);
            break;
        case ProductReviewType.Bad:
            PullBadReviews(context);
            break;
        default:
            //throw unhandled enum type
    }
}
Sign up to request clarification or add additional context in comments.

9 Comments

When trying to use ToString(); the compiler complains because the case statement is expecting a constant. I also know that ToString() is is striked out with a line in intellisense
@coffeeaddict: You can't use a runtime string values as case labels; however, you can easily use Enum.Parse() to get the value and then use the enum value names in the code. See my answer for an example. stackoverflow.com/questions/3120436/enum-value-to-string/…
Right, because the compiler doesn't know what Enum.ToString() is at compile time. If you want to switch on strings, you need to use constant strings, is "MyEnumValue";
+1 This way is cleaner as it makes sure action actually matches one of the Enum values. You can also specify to ignore case too.
If you downvote, please let me know why, so I can fix any mistakes. Thanks.
|
13

You're going about this backwards. Don't try to use dynamic strings as case labels (you can't), instead parse the string into an enum value:

private static void PullReviews(string action, HttpContext context) 
{ 
    // Enum.Parse() may throw if input is invalid, consider TryParse() in .NET 4
    ProductReviewType actionType = 
        (ProductReviewType)Enum.Parse(typeof(ProductReviewType), action);

    switch (actionType) 
    { 
        case ProductReviewType.Good: 
            PullGoodReviews(context); 
            break; 
        case ProductReviewType.Bad: 
            PullBadReviews(context); 
            break; 
        default: // consider a default case for other possible values...
            throw new ArgumentException("action");
    } 
} 

EDIT: In principle, you could just compare to hard-coded strings in your switch statements (see below), but this is the least advisable approach, since it will simply break when you change the values passed in to the method, or the definition of the enum. I'm adding this since it's worth knowing that strings can be used as case labels, so long as they are compile-time literals. Dynamic values can't be used as cases, since the compiler doesn't know about them.

// DON'T DO THIS...PLEASE, FOR YOUR OWN SAKE...
switch (action) 
{ 
    case "Good": 
        PullGoodReviews(context); 
        break; 
    case "Bad": 
        PullBadReviews(context); 
        break; 
} 

7 Comments

Voted up even though you should really have included a default case that throws :)
Probably want to use TryParse() instead, and handle bad inputs.
@LBushkin: So TryParse is included in .Net 4?
@simendsjo: Enum.TryParse() is available .NET 4.0, see: msdn.microsoft.com/en-us/library/dd783499.aspx.
Use a static extension for the string - .ToProductReviewType() and you will be absolutely golden!
|
5
public enum Color
{
    Red
}

var color = Color.Red;
var colorName = Enum.GetName(color.GetType(), color); // Red

Edit: Or perhaps you want..

Enum.Parse(typeof(Color), "Red", true /*ignorecase*/); // Color.Red

There is no TryParse for Enum, so if you expect errors, you have to use try/catch:

try
{
  Enum.Parse(typeof(Color), "Red", true /*ignorecase*/);
}
catch( ArgumentException )
{
  // no enum found
}

8 Comments

nice did not know of GetType vs. TypeOf
You might wanna update with an example of using TryParse() to show error handling.
@coffeeaddict: I will probably be slower as it works with boxing and inheritance - although I haven't tested, so it might be a very small hit
TryParse is available on enums in .Net 4.0 - msdn.microsoft.com/en-us/library/dd783499.aspx
About time to upgrade I guess... Seems I'm the only one left :|
|
2

This code is gonna works.

private enum ProductReviewType{good, bad};

private static void PullReviews(string action)
{
    string goodAction = Enum.GetName(typeof(ProductReviewType), ProductReviewType.good);
    string badAction = Enum.GetName(typeof(ProductReviewType), ProductReviewType.bad);
    if (action == goodAction)
    {
        PullGoodReviews();
    }
    else if (action == badAction)
    {
        PullBadReviews();
    }
}

public static void PullGoodReviews()
{
    Console.WriteLine("GOOD Review!");
}

public static void PullBadReviews()
{
    Console.WriteLine("BAD Review...");
}

Since the parsed string is not constant it can not be used by Switch statement. Compiled in VS2005

You can use another temp variable to save the Type of enum class, this may improve performance.

2 Comments

P.S. It may not a good idea to use enum in this way, but I know sometimes we just want it works.
thanks, interesting. That's what I was originally looking to do. I'll look this over again and keep this in mind moving ahead.
1

I'd suggest you go the other way - try to use the actual enum values as much as possible (by converting the string to an enum value as soon as you can), rather than passing strings around your application:

ProductReviewType actionType = (ProductReviewType)Enum.Parse(typeof(ProductReviewType), val);
// You might want to add some error handling here.
PullReviews(actionType);

private static void PullReviews(ProductReviewType action, HttpContext context)
{
    switch (action)
    {
        case ProductReviewType.Good:
            PullGoodReviews(context);
            break;
        case ProductReviewType.Bad:
            PullBadReviews(context);
            break;
    }
}

Note that I've changed your method signature to accept a ProductReviewType argument; this makes it clear what your method actually needs to implement its logic, and fits with my original point that you should try as much as possible not to pass strings around.

1 Comment

I ended up taking in a string as the first param then doing a Parse to transform it into the enum. The caller of this method needs to pass in a string from a querystring so it makes sense to parse in one location, inside this method.
1

This is just for the fun of it, but what if you used a dictionary of delegates? I realize that you have a completely different approach, but dictionary-izing might actually work better for what you're trying to accomplish, especially since it provides a high degree of modularity, as opposed to a mondo-switch construct (although I have to admit, your enum has only 2 members so its a moot issue). Anyways, I just wanted to air a different way to do things...

The dictionary-based approach would kind of look like this:

namespace ConsoleApplication1
{
    public enum ProductReviewType
    {
        Good,
        Bad
    }

    public static class StringToEnumHelper
    {
        public static ProductReviewType ToProductReviewType(this string target)
        {
            // just let the framework throw an exception if the parse doesn't work
            return (ProductReviewType)Enum.Parse(
              typeof(ProductReviewType), 
              target);
        }
    }

    class Program
    {

        delegate void ReviewHandler(HttpContext context);

        static readonly Dictionary<ProductReviewType, ReviewHandler> 
            pullReviewOperations = 
              new Dictionary<ProductReviewType, ReviewHandler>()
            {
                {ProductReviewType.Good, new ReviewHandler(PullGoodReviews)},
                {ProductReviewType.Bad, new ReviewHandler(PullBadReviews)}
            };

        private static void PullGoodReviews(HttpContext context)
        {
            // actual logic goes here...
            Console.WriteLine("Good");
        }

        private static void PullBadReviews(HttpContext context)
        {
            // actual logic goes here...
            Console.WriteLine("Bad");
        }

        private static void PullReviews(string action, HttpContext context)
        {
            pullReviewOperations[action.ToProductReviewType()](context);
        }

        static void Main(string[] args)
        {
            string s = "Good";
            pullReviewOperations[s.ToProductReviewType()](null);

            s = "Bad";
            pullReviewOperations[s.ToProductReviewType()](null);

            // pause program execution to review results...
            Console.WriteLine("Press enter to exit");
            Console.ReadLine();
        }
    }
}

2 Comments

my enum actually has around 5 but I did not post the enum :)
@coffeeaddict - in that case, why don't you use a dictionary of delegates? Plus the static extension on the string, and you should be golden...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.