I realize that I can select an element from an array from an enum by casting it as an int, but since I need to do that numerous times in my code, I was wondering if there is a way to set up a property or something like that to reduce code duplication. How would I be able to do something like this?
Casting an enum to an int extremely efficient. In fact, in most cases, the compiler does most of the work for you already. For example, using a constant like this arr[(int)MyEnum.Value] will be automatically compiled into an int literal like arr[7].
So there's really no need to try to speed this up.
However, if your enum values do not strictly range from 0 — n, (where n < array.length), then suggest using a Dictionary instead.
Related
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. E.g., 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, e.g.: 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 e.g. 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...
I'm reviewing code review suggestions written from/to various developers and came across an interesting one.
Someone originally wrote a basic comparison in LINQ (EF to be specific):
myTable.Where(i => i.MyValue == 1);
Where 1 is an unchanging TypeId stored in the database.
The suggestion was to remove the hard coded value of 1 in favor of a const. So for example it would be rewritten as:
const int valueId = 1;
myTable.Where(i => i.MyValue == valueId);
From the suggestion point of view I get where they were coming from with the const since the code only ever needs a single copy of this value. But perhaps the compiler is smart enough to recognize that this is an unchanging value and treats it similarly.
So the question remains, does this kind of code refactor actually hold any weight other than eliminating "magic numbers"?
At this level, it is highly unlikely it matters what is produced at the compiler. It is likely the same anyway. The point is, what is safer for usage and easier to understand? Does '1' represent anything in particular except the literal value '1'? Based on the code snippet, I would guess that it does, and that is very good grounds for introducing a constant field because you now know exactly what is being checked against here.
Is this literal value '1' used in any other places that would need to be changed if the value change, for example, to '2'? If so, that also is very good grounds for introducing a constant field because now you only have to change the value in a single place, rather than search your entire code base, and most likely missing at least one instance.
Also, credit to Ixrec from Programmers, valueId is a terrible name for a constant as it does not say what the value is. A better name would be answersId, if, for example, the '1' represented answers while '0' represented questions and '2' represented comments.
First of all, both versions of the code will compile to exactly the same IL.
A constant is not a variable. Any usage of a constant is replaced at compile-time by it's value.
There are 2 advantages of using a const instead of a literal
The constant can be defined once and used in many places. So if you ever need to change the value of the constant, you only need to change it in one place*
You can give a meaningful name to the constant.
(*) Never change value of a public const field - all other assemblies using this constant will have to be recompiled to use the updated value.
I've run into this pattern repeatedly in a project I'm working with:
int myIntValue = int.Parse(myNumericUpDown.Value.ToString());
This seems a little bit bananas to me, get a string from a decimal and then parse the string to get an int, and I wonder if there is something I'm missing that necessitates it. Seems like it has to be deliberate. Is there a reason that should be used rather than the obvious approach:
int myIntValue = (int)myNumericUpDown.Value;
Or:
int myIntValue = Convert.ToInt32(myNumericUpDown.Value);
Of course we cannot look into the mind of the programmer who wrote that code initially, but doing numeric conversions through strings is quite common with newer programmers. Presumably they first wrote
int myIntValue = myNumericUpDown.Value
got a compiler error, found Int32.Parse and put the pieces together.
There is really no reason at all to convert it to a string first, and then parse an integer from that - if anything it is inefficient and awkward to read.
In fact note that if for whatever reason the ToString gives an actual decimal number (like 3.0 instead of 3) the code will throw a System.FormatException which is not caught. From the assumption that you are not seeing that exception when running, I deduce that the control is set such that the Value property is always an integer, never something like 1.932, hence I would argue that the fastest way to get it as an integer is a hard cast
int myIntValue = (int)myNumericUpDown.Value;
(and add a try/catch for the inevitable case that your form designer messes up and sets the initial value of the control to 0.5).
This question is a bit opinionated, but I wanted some input. I have two static methods for creating ranges within a list. I can define a range in terms of a start and stop index or in terms of an index and a count. Here are the names I have so far:
public static Range FromStartAndStopIndex(int startIndex, int stopIndex);
public static Range FromIndexAndCount(int startIndex, int count);
I think these names are too long, but at least there's no ambiguity. I am sure there are other libraries out there that define ranges within a list. I am curious what names they have used to define ranges in different ways.
.NET tends to use index and count. For example:
String.Substring
Enumerable.Range
Stream.Read
Array.Copy
(Most relevant, probably) ArraySegment<T>
I would go with this, and only support the one model. Aside from anything else, when you've got an "end" parameter you then need to say whether it's inclusive or exclusive. (It should almost always be exclusive, but it's something else to clarify.)
On the other hand, SortedSet.GetViewBetween necessarily takes lower and upper bounds. That's somewhat different though.
I have an XML file that contains a "script" of items to check and validate. What it does is reads in a value to check, and if that check is true, it does something. I originally wrote this to work with just integers, but I realize I need to make it work with more data types.
A sample check is like this...It sees if SomeValue is greater than 20.
<If field="SomeValue" test="#gt" value="20" />
*The field is just some string value. So for a double, the field would be something like 55.7.
All I do is do a int.TryParse on the value to see if I can cast the string (SomeValue) to an integer. If I can, I check to see if it is greater than 20. If not, I just assume false on the check.
Does anyone have any suggestions on how I could this with any data type? (i.e. string, double, DateTime)
Would Generics work? I have never used them so I dont know if they would be the best solution. Thanks.
The tricky bit is a parse when you don't know the types, but this can be done with TypeDescriptor.GetConverter:
object knownVal = 21; //perhaps obtained from reflection
Type type = typeof(int);
string text = "20";
object val = TypeDescriptor.GetConverter(type)
.ConvertFromInvariantString(text);
int rel = Comparer.Default.Compare(knownVal, val);
Generics is an option (especially with Comparer<T>.Default.Compare), but generics doesn't mix well with Type values only known at runtime. It can be done (MakeGenericType/MakeGenericMethod), but it is ugly and a bit slow.
To be honest, though: if it was me I would assume there is a small number of types that need handling here, and special-case them.