What happens with enum when it is not set? - c#

I have the following cast:
int myInteger = (int)myItem.EnumValue;
Where the enum is:
public enum EnumValue
{
Yes= 0,
No = 1
}
From my observations it seems that when the EnumValue on myItem is not set, the value of EnumValue is on default set to Yes and subsequently cast to 0.
Why is the enum not null? Is my observation correct and why is it so?

Enum's are value types, so just like int's and other value types, they cannot be null. Instead their default value is the equivalent of 0 (since you've assigned an enum value of Yes to 0, that's the default value in this case).
If you want a nullable enum, use Nullable<EnumValue> or EnumValue? for short.
Further Reading
Value Types (C# Reference)
enum (C# Reference)
Nullable Types (C# Programming Guide)

Because enum variable is essentially a variable of enum underlying type. By default it is integer. Integer cannot have null value.
UPDATE: Under hood enum looks like
class public auto ansi sealed EnumValue extends [mscorlib]System.Enum
{
.field public static literal EnumValue Yes = int32(0x00000000)
.field public static literal EnumValue No = int32(0x00000001)
.field public specialname rtspecialname int32 value__
}
I.e. its a set of constants (which are inlined during compilation) and integer (by default) field which holds enum value. Thats why you can assign any integer value to variable of EnumValue type. That's why by default it has value 0. That's why it cannot be null.

Several answers suggest using a nullable enum, but you can also build similar logic into your enum without the overhead of the Nullable type:
public enum EnumValue
{
Unknown = 0,
Yes = 1,
No = 2
}
Since the enum's default value is 0, the default value is Unknown. Note that the default value is zero even if you don't define a field with the value zero, like this:
public enum EnumValue
{
Yes = 1,
No = 2
}

Why is enum not null?
Because enum is a value type, which can never be null.

The underlying type of an enumeration is always integral. From the docs:
Every enumeration type has an underlying type, which can be any
integral type except char. The default underlying type of enumeration
elements is int.
Since yours is based on int, the default value of the enum is the default value of an integer - which is zero.

Related

How the default value initialized even not specified in explicit constructor in c#

Declared variable and not initialized in explicit constructor. Then how the default value initialized to the variable.is it initialization done by the implicit constructor?
Ex:
class A
{
int i;
public A()
{
}
}
class program
{
static void Main(string[] args)
{
A a = new A();
Console.Write(a.i);
}
}
Output:
0
If you don't initialize a member variable then it gets assigned the value default(T) where T is the type.
For reference types this is null. For bool it is false and for other value types it is whatever the state of the object would be it the memory for it was zeron-initialized. Thus for int it it 0.
int is a value type and cannot be null unless you declare it as a nullable int (int?). It’s default value is 0.
you have taken i as int, and Integer is value type with a default value is 0
Check below link, if you're new in C#
Default Value
Value Type
Reference Type
Use ?, If you don't want to assign a default value. see below example

Initialize enum with a null value

How do i create an enum with a null value
ex:
public enum MyEnum
{
[StringValue("X")]
MyX,
[StringValue("Y")]
MyY,
None
}
where None value is null or String.Empty
You can try something like this:-
public MyEnum? value= null;
or you can try this:-
public MyEnum value= MyEnum.None;
As all the other answers said, you can't have an enum value be null.
What you can do is add a Description attribute (like your StringValue) which has a null value.
For instance:
public enum MyEnum
{
[Description(null)]
None = 0,
[Description("X")]
MyX,
[Description("Y")]
MyY
}
You can get the description of the Enum with the following function:
public static string GetEnumDescription(Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute),
false);
if (attributes != null && attributes.Length > 0)
return attributes[0].Description;
else
return value.ToString();
}
Usage:
MyEnum e = MyEnum.None;
string s2 = GetEnumDescription((MyEnum)e); // This returns null
use the "?" oeprator for a nullable type !!
public MyEnum? myEnum= null;
All enum types are value types and the different members are also derived from member types (the allowed types are byte, sbyte, short, ushort, int, uint, long, or ulong - as documented).
This means that members of an enumeration cannot be null.
One way to deal with a default enum value is to put the None value as the first value and setting it to a negative value (for signed enums) or 0.
public enum MyEnum
{
[StringValue(null)]
None = -1,
[StringValue("X")]
MyX,
[StringValue("Y")]
MyY
}
You can have a null reference to an enumeration if you declare a nullable instance - myenum?.
There is no such thing as an "enum with a null value". An enum in C# is just a named integer. In your case, None is just an alias for 2 (for completeness, MyX is 0 and MyY is 1). By default, the underlying data-type of an enum is int, but it can also be other integer-based primitive types of different sizes/sign.
If you want a "null" enum, you would have to use MyEnum?, aka Nullable<MyEnum>.

Values of enum as result of a function

I have three enums:
enum ValueType : int
{
FloatingPoint = 2,
.../...
}
enum ConstraintType : int
{
Range = 2,
.../...
}
enum Parameter : int
{
ExposureTime = F(ValueType.FloatingPoint, ConstraintType.Range, 23),
.../...
}
The problem is in the signature of F if I use:
private static int F(ValueType _V, ConstraintType _C, int _N) { ... }
I get an error (invalid arguments) for every call in the definition of Parameter, but if I use the following instead:
private static int F(int _V, int _C, int _N) { ... }
Everything is fine.
It's not a blocking problem, but I'd like to understand why is that.
The C# spec states in section 14.3 ("Enum members") that
Within an enum member initializer, values of other enum members are
always treated as having the type of their underlying type, so that
casts are not necessary when referring to other enum members.
As far as I can tell this is why the arguments appear to have a type of int. It's interesting to note that this will not result in an invalid argument error:
ExposureTime = F((ValueType)ValueType.FloatingPoint,
(CostraintType)ConstraintType.Range,
23),
Of course it will still result in another error because you cannot use a method call to initialize enum members as Marc says. A method call is not a constant expression, while
The associated value of an enum member is assigned either implicitly
or explicitly. If the declaration of the enum member has a
constant-expression initializer, the value of that constant
expression, implicitly converted to the underlying type of the enum,
is the associated value of the enum member. If the declaration of the enum member has no initializer, its associated value is set implicitly [...]
For enums with explicit values, the value must be a constant expression. F(...) is not a constant expression. Regardless of whether the parameters are int or enums, you cannot assign an enum value from a function call.
Your "everything is fine" actually means:
The expression being assigned to 'blah.Parameter.ExposureTime' must be constant
The only "problem" here is that the compiler doesn't give a very elegant error message to a particular illegal scenario.

Use EnumType.None, or Nullable<EnumType>?

Enums are generally used to define the state of a particular property of a class, say in an object model of some sort. For some of these properties, the state 'this property is not set' is valid.
In these situations, should I use a zero None enum value, or make the property type nullable?
public MyEnum Property { get; set; }
public enum MyEnum {
None = 0,
Value1,
Value2
}
or
public MyEnum? Property { get; set; }
public enum MyEnum {
Value1,
Value2
}
Use MyEnum.None - it is much more expressive, or even MyEnum.Invalid to convey meaning.
You can also set it to other values than 0 - since it is based on int, you can set it to be -1 and the first valid value to 1:
public enum MyEnum {
InvalidValue = -1,
Value1 = 1,
Value2
}
In your code you can easily check for this value being passed in and throw a descriptive exception.
A nullable enum type is not expected and less expressive. It requires users of you code to be aware of this and check for nulls.
It's hard to answer this conclusively, a lot of factors in your app will influence this. I tend to just define the enum value to 0, but not specify a zero value in the enum.
enum Foo
{
A = 1,
B = 2
}
...
Foo myFoo = (Foo)0;
This gives the benefit of a sentinel value, without polluting the enum.
I would use the "None" value instead of a nullable enum. If nothing else, to me if(Property == MyEnum.None) is a lot more readable than if(Property == null).
Another option is to set the first value to 1, since it will be initally 0.
public enum MyEnum {
Value1 = 1,
Value2
}
I think both of your situations are acceptable! It will depend upon your situation. When working with a user interface your first example with the 'None' value will probbaly be easier to use. However, the Nullable gives more information about how the variable should be used.

? (nullable) operator in C# [duplicate]

This question already has answers here:
What is the purpose of a question mark after a value type (for example: int? myVariable)?
(9 answers)
Closed 5 years ago.
What is changed by applying nullable Operator on value type datatype that now it can store null.
As others have said, "?" is just shorthand for changing it to Nullable<T>. This is just another value type with a Boolean flag to say whether or not there's really a useful value, or whether it's the null value for the type. In other words, Nullable<T> looks a bit like this:
public struct Nullable<T>
{
private readonly bool hasValue;
public bool HasValue { get { return hasValue; } }
private readonly T value;
public T value
{
get
{
if (!hasValue)
{
throw new InvalidOperationException();
}
return value;
}
}
public Nullable(T value)
{
this.value = value;
this.hasValue = true;
}
// Calling new Nullable<int>() or whatever will use the
// implicit initialization which leaves value as default(T)
// and hasValue as false.
}
Obviously in the real code there are more methods (like GetValueOrDefault()) and conversion operators etc. The C# compiler adds lifted operators which effectively proxy to the original operators for T.
At the risk of sounding like a broken record, this is still a value type. It doesn't involve boxing... and when you write:
int? x = null;
that's not a null reference - it's the null value of Nullable<int>, i.e. the one where hasValue is false.
When a nullable type is boxed, the CLR has a feature whereby the value either gets boxed to a null reference, or a plain boxed T. So if you have code like this:
int? x = 5;
int y = 5;
object o1 = x;
object o2 = y;
The boxed values referred to by o1 and o2 are indistinguishable. You can't tell that one is the result of boxing a nullable type.
The ? syntax is syntactic sugar to the Nullable<T> struct.
In essence, when you write int? myNullableInt, the compiler changes it to Nullable<int> myNullableInt.
From MSDN (scroll down to "Nullable Types Overview"):
The syntax T? is shorthand for Nullable, where T is a value type. The two forms are interchangeable.
Nothing is changed on the value type itself, it's simply wrapped in a System.Nullable<T> struct.
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx
The type changes from what it used to be to a Nullable type.
If you had an int, and decided to make it an int?:
int myInt;
And you make it:
int? myInt;
it is now:
Nullable<int> myInt;
In reality.
In basic terms, a nullable type is a boxed version of the normal type that has an extra boolean field called hasValue on it.
When this field is set to false, then the instance is null.
Check out this answer for a bit more detail on the CLR implementation, and why they might have chosen it: Boxing / Unboxing Nullable Types - Why this implementation?

Categories

Resources