Enum.Parse() or Switch

2019-04-21 01:01发布

For converting a string to an enum, which of the following ways is better?

  1. This code:

    colorEnum color = (colorEnum)Enum.Parse(typeof(colorEnum), "Green");
    
  2. or this:

    string colorString = ...
    colorEnum color;        
    switch (colorString)
    {
        case "Green":
            color = colorEnum.Green;
            break;
        case "Red":
            color = colorEnum.Red;
            break;
        case "Orange":
            color = colorEnum.Orange;
            break;
        ....
    }
    

11条回答
干净又极端
2楼-- · 2019-04-21 01:04

I use the following, it gets you all the type safety while still not falling over when you add new values into the Enum, it's also very fast.

public static colorEnum? GetColorFromString(string colorString)
{
    colorEnum? retVal = null;
    if(Enum.IsDefined(typeof(colorEnum), colorString))
        retVal = (colorEnum)Enum.Parse(typeof(colorEnum), colorString);
    return retVal;
}

My test with 8 items in the enum shows this way to be faster than the switch method.

Or else you can use (the very slow way):

public static colorEnum? GetColorFromString(string colorString)
{
    foreach (colorEnum col in Enum.GetValues(typeof(colorEnum)))
    {
        if (col.ToString().Equals(colorString))
        {
            return col;
        }
    }
    return null;
}
查看更多
别忘想泡老子
3楼-- · 2019-04-21 01:07

And what about Enum.TryParse<TEnum> ?

string myColorStr = "red";
colorEnum myColor;
if(!Enum.TryParse<colorEnum>(myColorStr, true, out myColor))
{
    throw new InvalidOperationException("Unknown color " + myColorStr);
}
查看更多
做自己的国王
4楼-- · 2019-04-21 01:09

I find the switch variant horrible since you will have to modify the switch everytime you change the enum also.

I like to use the TryParse that belongs to your enum. So you can use it like this

string colorString = .....
colorEnum color;

colorEnum.TryParse(colorString, out color);

Or if you don't care about the case of the string

colorEnum.TryParse(colorString, true, out color);

The returnvalue of TryParse is true if the string was a valid enum, false if not.

查看更多
forever°为你锁心
5楼-- · 2019-04-21 01:10

Because you added the tag 'performance', I'm going to go with the switch.
Yes, you will have to change the cases when you rename/add/remove anything in the enum. Well that's just too bad then. Any variant of Enum.Parse/TryParse uses a lot of weird code and some reflection, just take a look inside the function with ILSpy or such. Then there is also the issue of accepting "-12354" and even a comma-separated list of valid names (resulting in all of them ORed together) even when the enum doesn't have a [Flags] attribute.

As an alternative, you could make a dictionary that translates enum names to values. It should actually be faster than the switch, because a switch on strings also goes through a dictionary but you save the actual switch part.

Obviously both ways cost some more maintenance than enum.parse and variants; whether it's worth it is up to you, since out of all of us only you have enough knowledge of the project to make the performance/coding-time trade off.

查看更多
冷血范
6楼-- · 2019-04-21 01:11

Number 1 simply on readability and maintainability. If you extend the enum you need to do no extra work, wheras with 2 you have to add more cases to the switch statement

查看更多
甜甜的少女心
7楼-- · 2019-04-21 01:16

Other than the fact that the two different code snippets doesn't do the same thing, I'd use this:

colorEnum color;
if (!colorEnum.TryParse(colorString, true, out color)
    color = colorEnum.Green;    // Or whatever default value you wish to have.

If you don't have .NET 4.0 then I'd do something like this:

public static TEnum ToEnum<TEnum>(this string strEnumValue, TEnum defaultValue)
{
    if (!Enum.IsDefined(typeof(TEnum), strEnumValue))
        return defaultValue;

    return (TEnum)Enum.Parse(typeof(TEnum), strEnumValue);
}

This is an Extension Method to string.

查看更多
登录 后发表回答