Recently I've discovered that any string that contains only numeric characters can be converted to enum in C#. For example, imagine there is an enum defined as follows:
public enum TestEnum
{
One = 1,
Two = 2,
Three = 3
};
I can perform a conversion of some random numeric string to TestEnum.
TestEnum testEnum = (TestEnum)Enum.Parse(typeof(TestEnum), "4");
Console.WriteLine(testEnum);
The value '4' of course does not get mapped to one of defined TestEnum values and the output would be just 4, however there would be no error, so this conversion is legal.
On the other hand, if I try to check whether this value defined in TestEnum:
Console.WriteLine(Enum.IsDefined(typeof(TestEnum), "4"));
I would receive False in the output.
This seems a little strange to me, taking into account that the following conversion of non-numeric string, e.g.
(TestEnum)Enum.Parse(typeof(TestEnum), "Test")
will throw System.ArgumentException.
I am confused with such behavior. Was it intentionally designed this way or is this just a coincidence?
Was it intentionally designed this way or is this just a coincidence?
I'm not sure I understand your question. The documentation seems completely clear to me:
Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object.
(Emphasis mine)
It also says:
If value is the string representation of an integer that does not represent an underlying value of the enumType enumeration, the method returns an enumeration member whose underlying value is value converted to an integral type. If this behavior is undesirable, call the IsDefined method to ensure that a particular string representation of an integer is actually a member of enumType
Clearly this is intentional behavior, and not just coincidental.
Note that you can always cast any value of the enum's underlying type (int in this case), to the enum type itself. The enum type feature does not enforce values of the enum to correspond to named value. So the parsing behavior is entirely consistent with the compile-time behavior of enum types.
I suppose one might debate whether the enum type should allow unnamed values to be used. But, given that one of the features of enum types is to allow for flag-based enums, whether or not they have the [Flags] attribute, and given that it would be inconvenient (to say the least) to have to name every single combination of every single flag one defines in an enum type, it seems reasonable that they would go ahead and allow unnamed values for all types of enum types.
Related
What is the goal of explicitly casting an enum to it's declared type in, for example,
enum MyEnum : long
{
Zero,
One,
};
long one = (long)MyEnum.Zero; // <-- explicit conversion
Is there a logical explanation for this?
There are a few reasons but the main one that I use it for is when saving the field to a DB. The column in the DB has a data type that is int (in my case) and I use the conversion to allow me to save the enum value in the table.
The underlying type of enum (long in your case) specifies only how much storage is allocated for each enumerator. The type of enum itself is System.Enum so you need explicit cast.
That declaration tells compiler that you will use large values, but enum is still enum and it will not implicitly convert to any type. It's to be sure you know what you're doing, I think.
From C# Reference http://msdn.microsoft.com/pl-pl/library/sbbt4032.aspx
In the following example, the base-type option is used to declare an enum whose members are of type long. Notice that even though the underlying type of the enumeration is long, the enumeration members still must be explicitly converted to type long by using a cast.
What's the point of having '0' as a default value for enum in C#? If I declare enumeration that starts with a different number:
enum Color
{
Blue = 1,
Green,
Red,
}
then var color = default(Color) - will return me '0'. I expected to see the minimum value instead. This behavior may cause problems if each member of the enumeration corresponds to some specific number and '0' is not a valid value.
Default value for all value types (including enum) is bitwise 0. As result it means that 0 is always possible value for enum even if it is not explicitly defined.
Here is the specification: Default values table
EDIT: for more details check MSDN for enumeration types - enum
enum is type which is special in a way the it sort-of derives from other value type (which normally not possible), but behaves as value type of its backing type. An enum can use only some integral values as backing type.
Note: as #archil points out enum value may contain any value of backing type, irrespective of list of constants enumerated in enum itself. For enums marked with "FlagsAttribute" this behavior is normally expected, but for normal enums it may not be intuitive.
We can only conjecture about why an aspect of the .NET framework was designed a certain way. For the most straightforward explanation, I'd like to highlight this remark from the MSDN documentation:
An enumeration is a set of named constants whose underlying type is
any integral type except Char. If no underlying type is explicitly
declared, Int32 is used.
Note that a .NET enumeration is essentially an extension of an integral type. The default value for integral types is 0, so it's reasonable (if somewhat inconvenient in the cases you've illustrated) for enumerations to inherit that behaviour.
There always is possibility for enum to have non-existent value. That is why Enum.IsDefined Method exists.
The default value of an enum E is the value produced by the expression
(E)0.
As has been stated in multiple answers so far, the "default" value for any fixed-size data structure is 0. The size of the structures memory is set to zero and that is considered "default". Now, if you want to define your own "default" value for an enum, you have multiple options. The easiest would be to write your own function to give you a "minimum valid enum"
private E GetDefaultEnum<E>()
{
return (E)(Enum.GetValues(typeof(E)).Cast<E>().Min<E>());
}
Usage:
enum Color
{
Blue = 1,
Green,
Red,
}
Color defaultColor = GetDefaultEnum<Color>();
MessageBox.Show(defaultColor.ToString()); // "Blue"
You can obviously alter how you determine a "default" value, but this way seems best suited to your needs.
Why is 0 the default enum value? Ease of runtime implementation. The default of any value type is bitwise 0, and presumably a null reference is represented by bitwise 0. Thus to initially construct an object with its default values, we only need to know its size; the runtime doesn't need to know or process anything about the object's structure. Similarly, the pre-defined value-type constructor can merely fill a memory range with zeroes.
Like it or not, that's how it is. What we need to do in response is when designing an enum, whatever name is a suitable default, give it the value 0. If there is no suitable default, then your methods accepting such an enum as a parameter might check that it's properly set, e.g.
void ProcessColor(Color c) {
if (c == 0)
throw new ArgumentException("Color is not set", "c");
//...
}
The point is probabbly is in having less positive integer possible value.
Why less positive?
To be able to treat enum with bit-shift operation correctly.
I'm naturally talking about default value, that can be changed by developer.
I am not sure why but...
Here is the doc about C# enum: http://msdn.microsoft.com/en-us/library/sbbt4032.aspx
Enumerators can use initializers to override the default values, as shown in the following example.
enum Days {Sat=1, Sun, Mon, Tue, Wed, Thu, Fri};
In this enumeration, the sequence of elements is forced to start from 1 instead of 0. However, including a constant that has the value of 0 is recommended. For more information, see Enumeration Types (C# Programming Guide).
They recommend you always include a placeholder enum value which corresponds to the value 0 otherwise you may run into problems. You could name this enum value something like Undefined or Default or something like that.
As I mentioned in my comment to your question though, my recomendation would be to not use values for your enums at all unless you have a very good reason for doing so. If you need to, follow the MSDN Programming Guide for Enumeration Types
enum is int (by default). Enums are human-readable ints for our source code, but when your program gets compiled, there is no enum, only ints. The default value for int is 0.
This code:
public enum test { One, Two, Three }
var x = test.One;
var y = 0;
Becomes this in IL:
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: ldc.i4.0
IL_0004: stloc.1
So, how could an int have a default value of 1 (as you ask) in some cases, but not others?
Are enum types stored as ints in C#?
Will the enum below be represented as 0, 1, 2?
If not, what's the lightest way to define an enum?
public enum ColumnType
{
INT,STRING,OBJECT
}
From the MSDN
The default underlying type of enumeration elements is int.
By default, the first enumerator has the value 0, and the value of each successive enumerator is increased by 1.
So your assumptions are correct. Enums are stored as ints and your example will be represented as 0, 1, 2. However, you shouldn't rely on this and always refer to them by their assigned name just in case someone overrides the default.
Yes, an enum is stored as an int by default., as indicated here.
You can also specify the underlying type, e.g.:
enum Foo : short
{
Bar,
Baz
}
Although that usually isn't necessary.
By default yes:
http://msdn.microsoft.com/en-us/library/sbbt4032(v=vs.80).aspx
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. The default underlying type of the
enumeration elements is int. By default, the first enumerator has the
value 0, and the value of each successive enumerator is increased by
1.
The default underlying type for an enum is an int, but different types can be used explicitly. For example, you can use byte:
enum Days : byte {Sat=1, Sun, Mon, Tue, Wed, Thu, Fri};
See http://msdn.microsoft.com/en-us/library/sbbt4032.aspx for details.
Every enumeration type has an underlying type, which can be any integral type except char.
Yes your enum be represented as 0,1,2 by default and it is the lightest way to define an enum
How ever you define enum by defining starting value as your requirement and assigning integral values explicitly to each of your enum member as well
The point about underlying types is already well-covered, so I'll add a different context:
At the IL / runtime level, instances of enums do not exist. They only exist:
a: to the compiler
b: to the runtime as a boxed value
c: in metadata (parameter/field/variable declarations)
At all other times, they are purely the integer-types values (most commonly int). The compiler uses enum variables (etc) for static analysis, overload resolution, etc but the opcodes it emits are identical to those it would have emitted for constant / literal integer values; i.e.
SomeEnum foo = SomeEnum.WithValueOne;
int bar = 1;
will have identical IL (except for the variable type, perhaps).
The only time it gets interesting is if emitting a box operation, or a call like .ToString() etc.
So: as long as you don't box them (store them in an object field/etc), then there is (at runtime) no significant difference between an enum or an integer when it comes to storage or performance (unless you use .ToString(), etc)
We were having a debate if enums should have uninitialized values. For example. We have
public enum TimeOfDayType
{
Morning
Afternoon
Evening
}
or
public enum TimeOfDayType
{
None
Morning
Afternoon
Evening
}
I think that there shouldn't be any none but then you have to default to some valid value on initialization. But others thought there should be some indication of uniitized state by having another enum that is None or NotSet.
thoughts?
Speaking of nullable types - I think they can be used to solve the problem of forcing/not forcing the initialization of an enum. Say we have
enum Color { Red, Blue }
And let's say you have a function:
void Draw(Color c);
That function says that it requires a valid Color. However, we could also have this function:
void Draw(Color? c);
That says that the function can handle not being passed a color (null would be passed to indicate "don't care").
Well, it's one alternative to None members.
I always set one of my enum literals to zero. This literal must not always be named "None" or "NotSet". It depends if there is a literal which acts very well as default.
I set one to zero because, enums (except nullable enums) are always initialized by the CLR in memory to zero. And if you don't define one of the literals this memory contains illegal values. Also when you use enums as flags. The Default value cannot be used to do bitwise compairisons. The result will always be zero.
When you enable FxCop it checks if you have defined a literal as default. Seems to be a "good practice" when they have a rule for that.
A nullable enum was proposed as a solution in some of the previous answers. But a nullable enum has the disadvantage that it makes clients check for a null value every time they use the enum. On the contrary, if you have a default value of "None", you have the option to use a switch for the meaningful values and just ignore "None", without having to worry that the enum variable could be null.Anyway, I think having a default value of "None" or making the enum nullable makes sense only if the enum is used as an argument in a default constructor for some class. And you have to ask yourself - shouldn't the objects of that class have some meaningful default value? Using your example with the TimeOfDayType enum - if you initialize an object with TimeOfDayType.None, you can't use it anyway before you change the value to Morning, Afternoon or Evening. So couldn't you say that the default is Morning instead of None? Or - which is even better - couldn't you create your objects after you already know which enum value they need? I think that if the issue is correctly tackled with at the early design stages, you shouldn't need a special default value for your enums at all.Of course, all of the above is a generalization. Maybe it can't be applied to your particular scenario, so if you give some details about it, we could discuss the issue more thoroughly.
In the abscence of a "default" member, I think it's valuable to have a value representing the literal int 0.
No matter what, a given enum will be created with the literal value 0. The most straight forward case here is as a member of a struct. A C# struct will always have an empty default constructor that initalizes all fields to their default value. In the case of an enum, that will be the literal value 0. The question is how to handle it.
For me this is an issue of style: If the enum is not explicitly initialized to a value, should it be given an arbitrary valid value or a specific value indicating a lack of explicit initialization?
enum Color { Unknown, Red, Blue }
enum Color2 { Red,Blue }
struct Example<T> {
Color color;
}
static void SomeMethod() {
var v1 = new Example<Color>();
var v2 = new Example<Color2>();
}
In the case of v1, if the color field is inspected it will explicitly be labeled as an uninitialized field. In v2 the field will simple be "Red". There is no way for a programmer to detect between and explicit set to "Red" or an implicit default value to "Red".
Another case where this causes a problem is doing a switch statement against an enum value. Lets slighly alter the definition of Color2.
enum Color2 { Red = 1, Blue = 2 }
static void SomeOtherMethod(p1 as Example<Color2>) {
switch ( p1.color ) {
case Color.Red: {}
case Color.Blue: {}
default: {throw new Exception("What happened?"); }
}
}
The switch handles every explicit value in the enum. Yet this code will fail for the default constructor of Example<Color2> and there is no way to supress this constructor.
This brings up a slighly more important rule: Have an explicit enum value for the literal value 0.
Just adding to Franks answer, one of the only times I would opt for a 'None' item in an enum over nullable is when the enum is being used as flags. The 'None' item would be id of 0.
Depends how the type is used. It's often easier for users of the type not to have an "undefined" value, because you don't have to special-case one value. But if you need one (because values sometimes need to be in a state which is otherwise not any of the enumerated values) then you need one. You usually don't save any special-case code by using two enums instead of one.
It's a bit like asking whether you should use nullable types.
Are C# enums typesafe?
If not what are the implications?
To give a slightly different answer... while the values are type-safe from the casting perspective, they are still unchecked once they have been cast - i.e.
enum Foo { A = 1, B = 2, C = 3 }
static void Main()
{
Foo foo = (Foo)500; // works fine
Console.WriteLine(foo); // also fine - shows 500
}
For this reason, you should take care to check the values - for example with a default in a switch that throws an exception.
You can also check the (for non-[Flags] values) via:
bool isValid = Enum.IsDefined(typeof(Foo), foo);
Yes they are.
The following is from http://www.csharp-station.com/Tutorials/Lesson17.aspx
Enums are strongly typed constants. They are essentially unique types that allow you to assign symbolic names to integral values. In the C# tradition, they are strongly typed, meaning that an enum of one type may not be implicitly assigned to an enum of another type even though the underlying value of their members are the same. Along the same lines, integral types and enums are not implicitly interchangable. All assignments between different enum types and integral types require an explicit cast.
For those suggesting to use Enum.IsDefined to do argument validation...don't! Per Brad Abrams (from the Framework Design Guidlines Update on Enum Design):
There are really two problems with Enum.IsDefined(). First it loads reflection and a bunch of cold type metadata making it a deceptively expensive call. Secondly, as the note alludes to there is a versioning issue here.
Yes.
C#: enum types:
-A type-safe enumeration of named values.
-Prevents programming errors
-User can control underlying type (defaults to int)
-Also can control underlying values
Technically no because you can represent an Enum as its base value (int, long, etc). However, if you ensure that you only use the enum by its provided names, you will receive compile time errors if you change the name of an enumerated value without updating its references. In this regard yes it is type safe.
I'm late to the party here, but I wanted to throw out a little something extra ... An update to the .NET Framework Design Guidelines from Krzysztof Cwalina. In addition to the excellent tip above on checking to ensure a valid value is passed to your Enums, this provides other guidance and advice for how to use them effectively, a bunch of gotchas (especially involved Flags enums), etc.
yes they r strongly-typed safed u cannot it does not do impilcit convertion of enum constant variables to integeral value u hv 2 expilcitly do dat
eg
enum days {
sun,
mon
}
int e = (int ) days.sun;
console.writeline(e);
C# enums are type safe meaning
You cannot implicitly convert from the underlying type to the actual enum
Also, you cannot assign a value of one enum to another enum, even though the underlying types of both the enums are same. An explicit cast is always required.
Enums make your code more readable and more maintainable.
I have come accross an excellent video tutorial on enums exaplaining their type safe nature. Have a look here and there.