Just wondering if an enum can be null in C#?
Specifically I'm interested in the HttpStatusCode implementation of enum in C#.
What will happen if I will not assign a value to a variable of the HttpStatusCode
type? What will happen if I will try to assign a value that is not expected?
From MSDN:
Every enumeration type has an underlying type, which can be any integral type except char. The default underlying type of enumeration elements is int. To declare an enum of another integral type, such as byte, use a colon after the identifier followed by the type, as shown in the following example.
C#
enum Day : byte {Sat=1, Sun, Mon, Tue, Wed, Thu, Fri};
The approved types for an enum are byte, sbyte, short, ushort, int, uint, long, or ulong.
Since these are only value types, the enum itself cannot be null.
Of course you can wrap it in a Nullable, which allows value types to behave "nullable", but technically, Nullable<T> is a generic struct type (non-nullable) and not an enum itself, it's just a wrapper as by definition:
public struct Nullable<T> where T : struct
You might wonder: how can a struct be null? See this answer for an explanation:
Nullable<bool> b = new Nullable<bool>();
Basically, it's never null. It a compiler trick to guarantee that the values like e.g.: HasValue are always available.
HttpStatusCodes Enum
In your particular question about HttpStatusCodes.
What is actually happening is that the "code reader friendly" enum such as StatusCodes.400NotFound is just a representation of an integer value of 400. You can just manually use an integer value as the argument if you like, but then someone else reading your code may not understand the HTTP status code.
For example, if I just wrote in my code the status code422, is it easy to read / understand? Probably not a good idea. Someone reading your code will have a better chance if you use StatusCode.422UnprocessableEntity.
What are the valid HTTP status codes?
If you are sending back an HTTP response, you can designate any of the integer values listed here... https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
Unassigned or default behavior(s)?
Without knowing what method or what server you are using, your question about "what happens if it is unassigned". The usual answer is that the server will respond with a 200 (OK) status code as default.
Using non-standard response codes
It really depends on what you are doing, but using response code values that are not part of the standard (ex. -999) may (or may not) error, but you should avoid that as it is not a supported standard.
Nullable Enum
For HttpStatusCodes in all cases (I have ever experienced) you cannot assign a null value to the HttpResponse as the property type is integer.
Note that what I am saying is specific to assigning a status code value to a HttpResponse object. You can read the other answers about the generic question of nullable enums.
Not unless you make your variable of a Nullable<MyEnum> (or MyEnum?) type.
Under the hood, enums are integers. When an enum is uninitialized, it has the default(int) value, which is 0.
Edit: other underlying types are possible, but the default is int. Whichever underlying type you use, an uninitialized enum will always be the default value of the underlying type.
When you don't assign integer values to your enum, the first option will be set to 0 and therefore be the default.
public enum MyEnum { Foo, Bar, Baz }
MyEnum myEnum;
if(myEnum == MyEnum.Foo) //true
if(myEnum == MyEnum.Bar) //false
if(myEnum == MyEnum.Baz) //false
When you do assign integer values to your enum, and there is no 0 (or unassigned) value, then your uninitialized enum will not match any of the options.
public enum MyEnum { Foo = 1, Bar = 2, Baz = 3 }
MyEnum myEnum;
if(myEnum == MyEnum.Foo) //false
if(myEnum == MyEnum.Bar) //false
if(myEnum == MyEnum.Baz) //false
Related
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.
Normally, one would expect, and hope, that two casts are needed to first unbox a value type and then perform some kind of value type conversion into another value type. Here's an example where this holds:
// create boxed int
IFormattable box = 42; // box.GetType() == typeof(int)
// unbox and narrow
short x1 = (short)box; // fails runtime :-)
short x2 = (short)(int)box; // OK
// unbox and make unsigned
uint y1 = (uint)box; // fails runtime :-)
uint y2 = (uint)(int)box; // OK
// unbox and widen
long z1 = (long)box; // fails runtime :-)
long z2 = (long)(int)box; // OK (cast to long could be made implicit)
As you can see from my smileys, I'm happy that these conversions will fail if I use only one cast. After all, it's probably a coding mistake to try to unbox a value type into a different value type in one operation.
(There's nothing special with the IFormattable interface; you could also use the object class if you prefer.)
However, today I realized that this is different with enums (when (and only when) the enums have the same underlying type). Here's an example:
// create boxed DayOfWeek
IFormattable box = DayOfWeek.Monday; // box.GetType() == typeof(DayOfWeek)
// unbox and convert to other
// enum type in one cast
DateTimeKind dtk = (DateTimeKind)box; // succeeds runtime :-(
Console.WriteLine(box); // writes Monday
Console.WriteLine(dtk); // writes Utc
I think this behavior is unfortunate. It should really be compulsory to say (DateTimeKind)(DayOfWeek)box. Reading the C# specification, I see no justification of this difference between numeric conversions and enum conversions. It feels like the type safety is lost in this situation.
Do you think this is "unspecified behavior" that could be improved (without spec changes) in a future .NET version? It would be a breaking change.
Also, if the supplier of either of the enum types (either DayOfWeek or DateTimeKind in my example) decides to change the underlying type of one of the enum types from int to something else (could be long, short, ...), then all of a sudden the above one-cast code would stop working, which seems silly.
Of course, the enums DayOfWeek and DateTimeKind are not special. These could be any enum types, including user-defined ones.
Somewhat related: Why does unboxing enums yield odd results? (unboxes an int directly into an enum)
ADDITION:
OK, so many answers and comments have focused on how enums are treated "under the hood". While this is interesting in itself, I want to concentrate more on whether the observed behavior is covered by the C# specification.
Suppose I wrote the type:
struct YellowInteger
{
public readonly int Value;
public YellowInteger(int value)
{
Value = value;
}
// Clearly a yellow integer is completely different
// from an integer without any particular color,
// so it is important that this conversion is
// explicit
public static explicit operator int(YellowInteger yi)
{
return yi.Value;
}
}
and then said:
object box = new YellowInteger(1);
int x = (int)box;
then, does the C# spec say anything about whether this will succeed at runtime? For all I care, .NET might treat a YellowInteger as just an Int32 with different type metadata (or whatever it's called), but can anyone guarantee that .NET does not "confuse" a YellowInteger and an Int32 when unboxing? So where in the C# spec can I see if (int)box will succeed (calling my explicit operator method)?
When you use:
IFormattable box = 42;
long z2 = (long)(int)box;
You are actually unboxing and then casting.
But in your second case:
IFormattable box = DayOfWeek.Monday;
DateTimeKind dtk = (DateTimeKind)box;
You don't perform any casting at all. You just unbox the value. The default underlying type of the enumeration elements is int.
Update to refer to the real question:
The specification you mentioned in the comment:
The explicit enumeration conversions are:
...
From any enum-type to any other enum-type.
This is actually correct. We cannot implicitly convert:
//doesn't compile
DateTimeKind dtk = DayOfWeek.Monday;
But we can explicitly convert:
DateTimeKind dtk = (DateTimeKind)DayOfWeek.Monday;
It seems that you found a case when this is still required. But when combined with unboxing, only explicit conversion needs to be specified and unboxing can be ommited.
Update 2
Got a feeling that somebody must have noticed that before, went to Google, searched for "unboxing conversion enum" and guess what? Skeet blogged about it in 2005 (CLI spec mistake with unboxing and enums)
This is because they are actually represented as their underlying value type at runtime. They are both int, which follows the same situation as your failing cases - if you change the enum type in this situation, this would also fail.
As the type is the same, the action is simply unboxing the int.
You can only unbox values to their actual type, hence casting before unboxing does not work.
Update
If you create some code that casts int enumerations around with each other, you'll see that there are no casting actions in the generated IL. When you box an enum and unbox it to another type, there is just the unbox.any action which:
Converts the boxed representation of a type specified in the
instruction to its unboxed form.
In this case it is each of the enums, but they are both int.
Update 2:
I've reached my limit of being able to explain what is going on here without much more in-depth research on my part, but I spotted this question:
How is it that an enum derives from System.Enum and is an integer at the same time?
It might go a little ways to explaining how enumerations are handled.
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.