I've been writing C# for seven years now, and I keep wondering, why do enums have to be of an integral type? Wouldn't it be nice to do something like:
enum ErrorMessage
{
NotFound: "Could not find",
BadRequest: "Malformed request"
}
Is this a language design choice, or are there fundamental incompatibilities on a compiler, CLR, or IL level?
Do other languages have enums with string or complex (i.e. object) types? What languages?
(I'm aware of workarounds; my question is, why are they needed?)
EDIT: "workarounds" = attributes or static classes with consts :)
The purpose of an Enum is to give more meaningful values to integers. You're looking for something else besides an Enum. Enums are compatible with older windows APIs and COM stuff, and a long history on other platforms besides.
Maybe you'd be satisfied with public const members of a struct or a class.
Or maybe you're trying to restrict some specialized types values to only certain string values? But how it's stored and how it's displayed can be two different things - why use more space than necessary to store a value?
And if you want to have something like that readable in some persisted format, just make a utility or Extension method to spit it out.
This response is a little messy because there are just so many reasons. Comparing two strings for validity is much more expensive than comparing two integers. Comparing literal strings to known enums for static type-checking would be kinda unreasonable. Localization would be ... weird. Compatibility with would be broken. Enums as flags would be meaningless/broken.
It's an Enum. That's what Enums do! They're integral!
Perhaps use the description attribute from System.ComponentModel and write a helper function to retrieve the associated string from an enum value? (I've seen this in a codebase I work with and seemed like a perfectly reasonable alternative)
enum ErrorMessage
{
[Description("Could not find")]
NotFound,
[Description("Malformed request")]
BadRequest
}
What are the advantages, because I can only see drawbacks:
ToString will return a different string to the name of the enumeration. That is, ErrorMessage.NotFound.ToString() will be "Could not find" instead of "NotFound".
Conversely, with Enum.Parse, what would it do? Would it still accept the string name of the enumeration as it does for integer enumerations, or does it work with the string value?
You would not be able to implement [Flags] because what would ErrorMessage.NotFound | ErrorMessage.BadRequest equal in your example (I know that it doesn't really make sense in this particular case, and I suppose you could just say that [Flags] is not allowed on string-based enumerations but that still seems like a drawback to me)
While the comparison errMsg == ErrorMessage.NotFound could be implemented as a simple reference comparison, errMsg == "Could not find" would need to be implemented as a string comparison.
I can't think of any benefits, especially since it's so easy to build up your own dictionary mapping enumeration values to "custom" strings.
The real answer why: There's never been a compelling reason to make enums any more complicated than they are. If you need a simple closed list of values - they're it.
In .Net, enums were given the added benefit of internal representation <-> the string used to define them. This one little change adds some versioning downsides, but improves upon enums in C++.
The enum keyword is used to declare an
enumeration, a distinct type that
consists of a set of named constants
called the enumerator list.
Ref: msdn
Your question is with the chosen storage mechanism, an integer. This is just an implementation detail. We only get to peek beneath the covers of this simple type in order to maintain binary compatibility. Enums would otherwise have very limited usefulness.
Q: So why do enums use integer storage? As others have pointed out:
Integers are quick and easy to compare.
Integers are quick and easy to combine (bitwise for [Flags] style enums)
With integers, it's trivially easy to implement enums.
* none of these are specific to .net, and it appears the CLR designers apparently didn't feel compelled to change anything or add any gold plating to them.
Now that's not to saying your syntax isn't entirely unappealing. But is the effort to implement this feature in the CLR, and all the compilers, justified? For all the work that goes into this, has it really bought you anything you couldn't already achieve (with classes)? My gut feeling is no, there's no real benefit. (There's a post by Eric Lippert I wanted to link to, but I couldn't find it)
You can write 10 lines of code to implement in user-space what you're trying to achieve without all the headache of changing a compiler. Your user-space code is easily maintained over time - although perhaps not quite as pretty as if it's built-in, but at the end of the day it's the same thing. You can even get fancy with a T4 code generation template if you need to maintain many of your custom enum-esque values in your project.
So, enums are as complicated as they need to be.
Not really answering your question but presenting alternatives to string enums.
public struct ErrorMessage
{
public const string NotFound="Could not find";
public const string BadRequest="Malformed request";
}
Perhaps because then this wouldn't make sense:
enum ErrorMessage: string
{
NotFound,
BadRequest
}
It's a language decision - eg., Java's enum doesn't directly correspond to an int, but is instead an actual class. There's a lot of nice tricks that an int enum gives you - you can bitwise them for flags, iterate them (by adding or subtracting 1), etc. But, there's some downsides to it as well - the lack of additional metadata, casting any int to an invalid value, etc.
I think the decision was probably made, as with most design decisions, because int enums are "good enough". If you need something more complex, a class is cheap and easy enough to build.
Static readonly members give you the effect of complex enums, but don't incur the overhead unless you need it.
static class ErrorMessage {
public string Description { get; private set; }
public int Ordinal { get; private set; }
private ComplexEnum() { }
public static readonly NotFound = new ErrorMessage() {
Ordinal = 0, Description = "Could not find"
};
public static readonly BadRequest = new ErrorMessage() {
Ordinal = 1, Description = "Malformed Request"
};
}
Strictly speaking, the intrinsic representation of an enum shouldn't matter, because by definition, they are enumerated types. What this means is that
public enum PrimaryColor { Red, Blue, Yellow }
represents a set of values.
Firstly, some sets are smaller, whereas other sets are larger. Therefore, the .NET CLR allows one to base an enum on an integral type, so that the domain size for enumerated values can be increased or decreased, i.e., if an enum was based on a byte, then that enum cannot contain more than 256 distinct values, whereas one based on a long can contain 2^64 distinct values. This is enabled by the fact that a long is 8 times larger than a byte.
Secondly, an added benefit of restricting the base type of enums to integral values is that one can perform bitwise operations on enum values, as well as create bitmaps of them to represent more than one values.
Finally, integral types are the most efficient data types available inside a computer, therefore, there is a performance advantage when it comes to comparing different enum values.
For the most part, I would say representing enums by integral types seems to be a CLR and/or CLS design choice, though one that is probably not very difficult to arrive at.
The main advantage of integral enums is that they don't take up much space in memory. An instance of a default System.Int32-backed enum takes up just 4-bytes of memory and can be compared quickly to other instances of that enum.
In constrast, string-backed enums would be reference types that require each instance to be allocated on the heap and comparisons to involve checking each character in a string. You could probably minimize some of the issues with some creativity in the runtime and with compilers, but you'd still run into similar problems when trying to store the enum efficiently in a database or other external store.
While it also counts as an "alternative", you can still do better than just a bunch of consts:
struct ErrorMessage
{
public static readonly ErrorMessage NotFound =
new ErrorMessage("Could not find");
public static readonly ErrorMessage BadRequest =
new ErrorMessage("Bad request");
private string s;
private ErrorMessage(string s)
{
this.s = s;
}
public static explicit operator ErrorMessage(string s)
{
return new ErrorMessage(s);
}
public static explicit operator string(ErrorMessage em)
{
return em.s;
}
}
The only catch here is that, as any value type, this one has a default value, which will have s==null. But this isn't really different from Java enums, which themselves can be null (being reference types).
In general, Java-like advanced enums cross the line between actual enums, and syntactic sugar for a sealed class hierarchy. Whether such sugar is a good idea or not is arguable.
Related
What are some advantages of making enum in Java similar to a class, rather than just a collection of constants as in C/C++?
You get free compile time checking of valid values. Using
public static int OPTION_ONE = 0;
public static int OPTION_TWO = 1;
does not ensure
void selectOption(int option) {
...
}
will only accept 0 or 1 as a parameter value. Using an enum, that is guaranteed. Moreover, this leads to more self documenting code, because you can use code completion to see all enum values.
Type safety is one reason.
Another, that I find more important, is that you can attach metadata to enum values in Java. For example, you could use an enum to define the set of legal operations for a webservice, and then attach metadata for the type of request and data class:
AddItem(HttpMethod.POST, ProductEntry.class),
Java 5 enums originated from a typesafe enum pattern from Joshua Bloch's Effective Java (the first edition) to avoid the pitfalls of enums in C/C++/C# (which are simply thinly-veiled int constants) and the use in Java of final static int constants.
Primarily int constants and int enums aren't typesafe. You can pass in any int value. In C/C++ you can do this:
enum A { one, two, three };
enum B { beef, chicken, pork } b = beef;
void func(A a) { ... }
func((A)b);
Unfortunately the typesafe enum pattern from Effective Java had a lot of boilerplate, not all of it obvious. The most notable is you had to override the private method readResolve to stop Java creating new instances on deserialization, which would break simple reference checking (ie using the == operator instead of equals()).
So Java 5 enums offer these advantages over ints:
Type safety;
Java 5 enums can have behaviour and implement interfaces;
Java 5 enums have some extremely lightweight data structures like EnumSet and EnumMap.
Java 5 enums over these advantages over just using classes:
Less error-prone boilerplate (private constructor, readResolve() etc);
Semantic correctness. You see something is an enum and you know it's just representing a value. You see a class and you're not sure. Maybe there's a static factory method somewhere, etc. Java 5 enums much more clearly indicate intent.
Enums are already a class in Java.
If you're asking why this is better, I'd say that better type safety and the ability to add other attributes besides a mere ordinal value would come to mind.
In addition to better type safety, you can also define custom behavior in your enums (refer to Effective Java for some good examples).
You can use enums to effectively implement Singletons ^^:
public enum Elvis {
INSTANCE
}
Making enum a reference type that can contain fixed set of constants has led to efficient Map implementation like EnumMap and Set implementation like EnumSet (JDK classes).
From javadoc of EnumMap :
A specialized Map implementation for use with enum type keys. All of the keys in an enum map must come from a single enum type that is specified, explicitly or implicitly, when the map is created. Enum maps are represented internally as arrays. This representation is extremely compact and efficient.
EnumMap combines richness and type safety of Map with the speed of an array (Effective Java).
Enums are a type in itself - you cannot use an enum that does not exist, or put in some other similar looking constant. and also, you can enumerate them, so that code can be more concise.
using static constants could potentially cause maintenence nightmares - especially if they area spread out.
The only real advantage is that it can be used in a switch statement. All the other stuff an enum is capable of can just be done with plain vanilla class with a private constructor whose instances in turn are declared as public static final fields of the class in question (the typesafe pattern). The other advantage of enum is obviously that it makes the code less verbose than you would do with a plain vanilla class.
But if I'm not mistaken, in C++ (or was it C#?) you can use a String in a switch statement. So that advantage of enums in Java is negligible as opposed to C++. However, same thing was proposed for Java 7, not sure if it will make it.
Benefits of Using Enumerations:
An object can be created to work in the same manner as an enumeration. In fact,
enumerations were not even included in the Java language until version 5.0. However,
enumerations make code more readable and provide less room for programmer error.
OCA Java SE 7 Programmer I Study Guide
I have read a lot about the danger of using structures as a data type, I wonder if there is any problem with this one,
List<Summarized> SummarizedList = new List<Summarized>();
Summarized SumInfo;
struct Summarized
{
public string sBrand;
public string sModel;
public string sCustomer;
public int sline;
public string sLeader;
public int sDesire;
public int sReal;
}
As you can see I use a generic list of items type SumInfo which is the struct data type. whenever I need to update an item of the list I just do the following:
SumInfo = (Summarized)SummarizedList[CurrentPos];
SumInfo.sDesire = DesireProd;
SumInfo.sReal = RealProduced;
SummarizedList[CurrentPos] = SumInfo;
where CurrentPos is the position of the item I want to update.
Everything works fine so far, so could be any problem with that in the future? Is this struct one of the mutable ones?
Thanks.
Everything works fine so far, so could be any problem with that in the future? Is this struct one of the mutable ones?
Yes, it's a mutable struct. Yes, it will work.
However, I would argue that this struct should be a class. For details as to why, refer to Choosing Between Classes and Structures. In this case, you're violating 3 of the cases which should always be true for structs:
It logically represents a single value, similar to primitive types (integer, double, and so on).
It has an instance size smaller than 16 bytes.
It is immutable.
This would strongly suggest a class is more appropriate for your type. It would also simplify your code.
BTW - Side note, the cast is not required in your code above. You should be able to just write:
SumInfo = SummarizedList[CurrentPos];
Issues:
It's a mutable struct, and they're almost always a bad idea (search for "mutable structs evil" and you'll get loads of hits)
It's got public fields - therefore no encapsulation; no separation between the API of the type an its implementation
It's got public members which don't follow the normal .NET naming conventions
It doesn't logically represent a single value, as per the .NET design guidelines
It's larger than the 16 bytes recommended by the same guidelines (although I wouldn't pay too much attention to that if everything else were okay)
Basically it's a dumb data bucket. There's a time and place for that, but it should almost always be a class in that case, and I'd personally usually try to make it an immutable type as well.
is there any reason you're using a struct? if you made it a class, the List would just contain references, and your code would look like:
SumInfo = SummarizedList[CurrentPos];
SumInfo.sDesire = DesireProd;
SumInfo.sReal = RealProduced;
// you're done! no need to insert it back in, you're referring to the same item
Personally, I would have nothing against using this struct. It may depend more on how you use it, whether you encapsulate the List methods etc.
The mutability of it depends on whether you are expecting to update any antries once you have added them to the list. If you are not expecting to, then your STRUCT is immutable, but your list isn't. However in this case you are updating the entries, so it is.
I would concur that a class is probably a better option for this.
Issue 1:
Yes the struct is mutable. And it suffers from all the problems associated with that.
SummarizedList[CurrentPos].sDesire=DesireProd;
shows why using a mutable struct like this is a bad idea, since it will not change the struct in the list.
Issue 2:
You have public mutable fields. This is considered bad style and you should use properties instead.
Issue 3:
You're using (System) Hungarian notation. When developing in C# follow the .net naming conventions.
When reading Jon Skeet's answer to this particular question How can I make it so my class variables can only be set to one of three choices? y learned something new I was not aware of in C# and I guess the CLR type system.
What is the reasoning behind this being legal:
public enum Tests
{
Zero = 0,
One,
Two
}
var nonExistantTestsValue = (Tests)1000;
This will compile perfectly fine but I fail to see the reason of why it should be so. The whole point of enumerations as far as I can see is to limit to a certain number of options the value of a given variable of the specified type.
If the limitation imposed by the enum definition is so easily broken, what is the point (besides the readability issue)? You can obviously make sure it is a valid value using reflection but why isn't this done at compile time?
There is probably a good reason for this to work the way it does but I fail to see it.
Enumerations are essentially unique types that allow you to assign symbolic names to integral values. They are not used for restricting the allowable values of a variable...
If the limitation imposed by the enum definition is so easily broken, what is the point
I think the enum abstraction was not designed with limitation or guarantees in mind. I think it was designed with convenience and maintainability in mind
Good reasons:
Skip the first bullet if you don't want to see simple truths rigth now
the language specification [the reason I mention this is to remind people about the limited use of debating facts; a phrase like ... then what's the point triggers this for me]
performance (its hard/impossible to tell when a validation would not needed and this would hamper performance in a big way for specific applications
(Remember CLR functions can be called from anywhere, not just C#, not just your assembly)
It is more questioning in what you can do when enums are not limited to there values:
Flags is one of these examples:
[Flags]
enum MyFlag
{
a,
b,
c
}
Now you can do bit operations:
MyFlag flags = MyFlag.a|MyFlag.b;
It is allowed any value because you may mark the enum with the "Flags" attribute. That means you may compose any value by OR-ing various members of the enum itself.
Basically the compiler is not smart enough to take care of any possible way where the enum is used.
EDIT: found a previous post by Eric Lippert:
Why does casting int to invalid enum value NOT throw exception?
I don't know about the reasons for this design decision, but we can look at a few of its consequences.
Let's look at the IL representation of an enum:
.class private auto ansi sealed MyEnum
extends [mscorlib]System.Enum
{
// Fields
.field public specialname rtspecialname int32 value__
.field public static literal valuetype MyEnum Value0 = int32(0)
.field public static literal valuetype MyEnum Value1 = int32(1)
.field public static literal valuetype MyEnum Value2 = int32(2)
}
First we note that it is a value type and thus (MyEnum)0 must be valid. Second we see that the possible values of the enums are just consts and that enums at the runtime level are assignment compatible to integer literals.
Enum constants generally become an integer literal. So if you wanted to prevent invalid enums from appearing you'd need to introduce either expensive runtime checks when converting from an enum, or non trivial cross assembly load time checks to make sure enum literals baked into another assembly are valid.
Another thing is that it is possible to create enums backed by a long. But one property of longs is that their assignment is not guaranteed to be atomic. So guaranteeing that the value of a long based enum is valid is hard.
enum MyLongEnum:long
{
Value1=0x0101010102020202,
Value2=0x0303030304040404
}
If you assigned to such an enum from multiple threads you can end up with a mixed value that's invalid even if you never assigned an invalid value.
There is also an easy workaround to get safe enums: Use a class with a private constructor and static readonly fields or properties for the possible values. This way you lose integer conversions, literals and non-nullability, but gain type safety and better versioning.
There is no data loss by doing this, so what's the reason for having to explicitly cast enums to ints?
Would it not be more intuitive if it was implicit, say when you have a higher level method like:
PerformOperation ( OperationType.Silent type )
where PerformOperation calls a wrapped C++ method that's exposed as such:
_unmanaged_perform_operation ( int operation_type )
There are two primary and inconsistent uses of enums:
enum Medals
{ Gold, Silver, Bronze }
[Flags]
enum FilePermissionFlags
{
CanRead = 0x01,
CanWrite = 0x02,
CanDelete = 0x04
}
In the first case, it makes no sense to treat these things as numbers. The fact that they are stored as integers is an implementation detail. You can't logically add, subtract, multiply or divide Gold, Silver and Bronze.
In the second case, it also makes no sense to treat these things as numbers. You can't add, subtract, multiply or divide them. The only sensible operations are bitwise operations.
Enums are lousy numbers, so you should not be able to treat them as numbers accidentally.
Because enums do not have to be int based:
The enum keyword is used to declare an
enumeration, a distinct type
consisting of a set of named constants
called the enumerator list. Every
enumeration type has an underlying
type, which can be any integral type
except char.
So you can do something like this:
enum Something :long { valueX = 0, valueY = 2147483648L }
Why do you say no data loss? Not all enums are ints, after all. They must be integer-typed, but that can mean byte, ulong, etc.
As a corner-case the literal 0 is implicit, but; what would be your use-case here?
It is pretty rare I need to do this - usually data import etc. An occasional no-op cast makes perfect sense to me, and avoids accidental mistakes.
Would it not be more intuitive if it was implicit, say when you have a higher level method like:
I actually think not. In this case, you're trying to use an Enum in an edge case.
However, if enums were implicitly converted to integer values, this would dramatically reduce their effectiveness. By forcing an int conversion explicitly, the compiler is treating enum as a special type - one of many options, not as an integer. This more clearly demonstrates the intent of the enum, and reduces the chance of programmer mistakes (ie: assigning values that aren't defined in the enum to an enum variable, etc).
I personally am glad that enum in C# is more than (effectively) a constant int value.
I think that the answer to "Why enums require an explicit cast to int type?" is that strongly-typed enums as per C# are a useful defence against common programming errors.
Imagine I had a painting management application, based on two enums:
enum Textures { Gloss, Satin, Matt };
enum Colors { White, Green, Red, Blue, Brown };
And a room-painting method like this:
private void PaintRoom (Textures texture, Colors color)
In a language with strong enum typing like in C#, a command like this:
// nonsensical attempt to have texture=White and color=Matt
PaintRoom(Colors.White, Textures.Matt);
...would yeild a compile-time error (can't put color into where a texture is expected and vice versa). But in languages where the enums aren't strongly-typed and/or implicit conversion can occur (including C and C++), both our Colors and our Textures can be treated as int, so we can happily issue a PaintRoom(Colors.White, Textures.Matt) command and it will compile fine, but we end up with a room painted Gloss Red (0, 2) instead of the Matt White (2, 0) that we intended and the code on a quick glance seems to say.
So strongly-typed enums are mostly a good thing, to stop people accidentally putting enums into places they were not meant for. And where someone really wants their enum as an int, C# forces the coder to make their intention clear by insisting on an explicit conversion.
That is the way C# works...
If Enum had inherited from int, then this should be possible. Enum doesn't inherit from int, and therefore, a cast is required.
The only way to implicit cast classes, is if they inherit.
As others have said, it is impossible to change the required cast from EnumType to int. However, there are several workarounds. For instance, I have several enums that refer to similar things, and wanted to be able to assign any of them to a variable. So I went with:
public ValueType State {
get {
return state;
}
set {
state = (int)value;
}
}
and thus, I could say both playerObject.animator.State = Player.STANDING and monsterObject.animator.State = Monster.DROOLING, implicitly as far as the calling class could tell.
Also, yes, there is a legitimate reason why I have to treat enum values as numbers.
1) I’m aware of the following benefits:
they increase the level of abstraction since you immediately see what underlying integral values represent.
You can use them instead of magic numbers and by doing that making the code more understandable
They also restrict the values an enum variable can have and in doing so make the application safer, since programmers know which values are valid for variable, so I guess they sort of provide a type safety
Are there any other benefits they provide over directly using integral values?
2) Why do they use integrals as an underlying type and not string?
thank you
You've listed a lot of the core reasons where enums are preferable to integral types.
Named constants are safer and more readable than magic numbers
Enums describe to programmers what they are for. Integral values don't.
Naturally limiting the set of values that can be passed in. (You've got the tip of the type-safety iceberg... but look deeper...)
You can also add:
Vastly increased Type Safety. If you accept an 'int', then any int can be passed in. If you accept a VehicleType, then only a VehicleType can be passed in. I'm not just talking about someone passing in 6 when the largest allowed number is 5. I mean what if you pass in FuelType.Unleaded to a function that thinks it means VehicleType.Aeroplane? With enums the compiler will tell you you're an idiot. An integral type says "yeah, 5 is fine with me" and your program exhibits really odd behaviour that may be extremely difficult to trace.
Easier refactoring. Just as with any magic constants, If you pass in the value 5 in a hundred places in your program, you're in trouble if you decide to change 5 to have a different meaning. With an enum (as long as you don't have binary backwards compatibility concerns) you can change the underlying values. You can also change the underlying type of an enum if you wish (byte -> int -> long) without having to do anything more than recompile the client code.
Bitfields are so much easier to work with when the bits and masks can be named. And if you add new bits, you can often arrange things so that merely updating the related masks will allow most of your existing code to handle the new bitfields perfectly without having to rewrite them from scratch.
Consistency throughout the program. If you are careful with obfuscation and type safety, enums allow you to represent a list of named values that a user chooses from with the same names in the code, but without the efficiency cost of using strings.
Everybody understands why constants are great in code. Enums simply give you a way of holding together a related group of constants. You could achieve the same thing in a messier manner using a namespace of consts.
Using an enum for a parameter rather than a bool not only makes the code self-documenting, readable, and less prone to mistakes. It also makes it much easier to add a third option when you realize that two options isn't enough.
As with all tools, enums can be misused. Just use them where they make sense.
2) Why use bytes or ints instead of strings? Simply they're small and efficient.
I would conjecture that they require underlying integral types to ensure simplicity of comparison and more easily support bit flags. Without that limitation, we, or the compiler, or the runtime, would likely have to resort to some fuzziness to do things like combinations - or we would get into a situation where - as you say - we shouldn't care about the underlying type (the point of the abstraction) and yet when we try to say A | B we get a runtime error because we used an underlying type that isn't capable of that type of operation.
One benefit is when you want to use enum as a flag.
So if you define an enum like this:
[Flags]
public enum TestEnum{ A, B, C, D };
Then if you have a method that accept an instance of TestEnum as a variable, you can combine the values from the enum, so you can send for example A | B | C as the parameter for the method. Then, inside the method, you can check the parameter like this:
if ((paramname & TestEnum.A) > 0)
{
//do things related to A
}
if ((paramname & TestEnum.B) > 0)
{
//do things related to B
}
//same for C and D
Also, I think the reasons you mention are good enough by themselves to use enums.
Also regarding the comment that you can force an wrong value into an enum with code like this (TestEnum)500; it's hard to do if you do not want to break your code.
The point that the value 0 for an enum should be the default value, or in the case of flags "the absence of all other flags" is very important, since the line TestEnum myenum will instanciate myenum as 0 regardless if you have defined any enum value for 0 or not.
You can also parse an Enum from the string representation. You may get that string from a data source or user-entry.
I think you sold me on Enums at "magic numbers".
The main benefit of enum is that constants can be referred to in a consistent, expressive and type safe way.
Readability is of-course the topmost advantage of using the enumeration.
Another advantage is that enumerated constants are generated automatically by the compiler.
For instance, if you had an enumerated constant type for error codes that could occur in your program, your enum definition could look something like this:
enum Error_Code
{
OUT_OF_MEMORY,
FILE_NOT_FOUND
};
OUT_OF_MEMORY is automatically assigned the value of 0 (zero) by the compiler
because it appears first in the definition.FILE_NOT_FOUND equal to 1, so on.
If you were to approach the same example by using symbolic constants or Magic numbers, you write much more code to do the same.