简体   繁体   中英

Enum methods vs string methods

Is it more efficient to use enums instead of string arrays, performance-wise?

I decided to test a particular method IsDefined, versus checking for a match-up inside a string array. I created an object of Stopwatch to test the runtime for each one.
The code, below:

Defined an enum outside of class Main:

 enum Color : byte { red, blue, green }

Inside Main:

string[] colArr = new string[] { "red", "blue", "green" };
string input = "green";
Stopwatch s1 = new Stopwatch();
int loopIterations = 0;

s1.Restart();
while (loopIterations++ < 100000000)
    foreach (var blah in colArr)
        if (blah == input)
            break;
s1.Stop();
Console.WriteLine("Runtime for foreach loop: {0}", s1.Elapsed);

loopIterations = 0;
s1.Restart();
while (loopIterations++ < 100000000)
    if (Enum.IsDefined(typeof(Color), input))
        continue;
s1.Stop();
Console.WriteLine("Runtime for IsDefined method returned value: {0}", s1.Elapsed);

And my output looks like this:

Runtime for foreach loop: 00:00:01.4862817
Runtime for IsDefined method returned value: 00:00:09.3421654
Press any key to continue . . .

So I wanted to ask if - assuming the code I wrote isn't, like, stupid or something - those numbers are normal, and if they are, in what way is using enums preferable to using a string array, specifically for the kind of jobs both would?

For starters, rather than performance a big reason for using enums over strings is maintainability of the code. Eg, trying to 'find all references' to Color.red can be done with a few clicks in visual studio. Trying to find strings isn't so easy. Always typing the strings is also error-prone. Although both problems could be alleviated somewhat by using constants, it's easier to use enums.

An enum can be seen as a constant integer value, which has good performance and has benefits such as using flags (masks). Comparing an int will be faster than comparing a string, but that's not what happens here. Mostly you want to do something for a specific value and you could test if(someString == "red") versus if(someColVal == Color.red) , in which case the latter should be faster.

Checking if a value exists in an enum can be slower with the Enum.IsDefined , but that function has to look up the enum-values each time in this loop. Meanwhile the first test has a pre-defined array. For the strict comparison in performance to your first test, you could do something like:

var colvalues = Enum.GetValues(typeof(Color)).Cast<Color>().ToArray();  // or hardcode: var colvalues = new[]{Color.red, Color.blue, Color.green};
var colinput = Color.red;
while (loopIterations++ < 100000000)
    foreach (var blah in colvalues)
        if (blah == colinput)
            break;

Although as stated, finding if a value exists in an enum is normally not its primary function (mostly it's used for checking for a specific value). However it's integer base allows for other methods to check if a value is in an expected range, such as mask-checking or > , >= , < or <=

edit Seeing the comments about user input: mostly the input would be controlled, eg: the user is shown a menu. In a console environment that menu could be build with the numbers of the enum. For example, enum enum Color : byte { red = 1, blue, green } , menu 1. red 2. blue 3. green

The user input would be an integer. On the other hand if typing is required, IsDefined would prevent having to retype the values and is good for ease of use. For performance the names could be buffered with something like var colvalues = Enum.GetNames(typeof(Color)).ToArray();

The normal use for enums is to represent logical states or a limited range of options: in your example, if eg a product ever only comes in three colours. Using a string to represent colours in such a case has two drawbacks: you may misspell the name of a colour somewhere in your code, and get hard to track bugs; and string comparison is inherently slower than comparing enums (which is basically comparing integers).

IsDefined() uses type reflection, and thus should be slower than straight string comparison. There are cases where you want to convert enums to and from strings: usually when doing input/output such as saving or restoring configurations. That's slower, but input/output is typically dominated by the slowness of storage media and networks, so it's seldom a big deal.

I know this is a very old post, but noticed the compared code snippets for the loops are not doing the looping in a similar fashion. As in the first loop, you let the loop break once it finds the string in the string array but in the second scenario you dont let the loop stop but rather continue if the Enum.IsDefined finds the value.

When you actually let the loop in enum scenario to break if it finds the value, the enum scenario runs much faster...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM