I would need to have an enum type variable that is not automatically initialized to value of the first element.
Is there any way how to do that?
Enum variables aren't always initialized to the first value of the enum.
For instance / static variables, they're initialized to the "0" value of the enum - which may not be a named value, e.g.
enum Color
{
Red = 1,
Blue = 2,
Green = 3
}
Color c; // This will be 0
Local variables aren't initialized automatically - they have to be definitely assigned before the first point at which they can be read, just like any other variable.
It's not really clear what you're trying to achieve - if you could give more details of the context, that would help a lot. Using a nullable value type might be what you want, or you may just want to force initialization within a constructor, for example.
Technically the enum is initialized with 0, not with the first value:
enum Test {
Second = 1,
Third = 2
}
Test test;
void Main()
{
Console.WriteLine("{0}", (int)test);
}
// Result: 0
From MSDN: The default value of an enum E is the value produced by the expression (E)0. http://msdn.microsoft.com/en-us/library/sbbt4032(v=vs.80).aspx
No way, unless you use Nullable<SomeEnum>.
You can consider making it nullable
An enum has an underlying data type of int (by default), and just like an int wi always be initialized, so will the enum.
Your best bet is to add the value Uninitialized as the first entry in the enum.
So for example
public enum MyEnum{ Uninitialized, EnumValue1, EnumValue2, ... };
Then create a instance of it
MyEnum enumInstance;
Now it will still be initialized to the first element in the enum, but you also know that it means you have not initialized it yet.
The enum keyword is used to declare an enumeration, a distinct type consisting of a set of named constants called the enumerator list.
If you wish to represent an unknown value in the enum, you can do it by adding an element Unknown with value 0.
You could declare the field as Nullable< MyNullableEnum >
A helpful link :
Should enums have uninitialized values.. ?
Related
I expect the following call to the Parse method to return the enum member EN_CA but it returns EN instead.
Enum.Parse(LanguageType, "EN_CA", true);
where:
enum LanguageType
{
EN = 0,
EN_CA = 0,
FR = 1
}
It seems like the Parse method just grabs the first member that maps to the value of the parameter that is passed into it.The Parse method seems to be loosing information during the conversion from string to enum member. Changing the order of EN_CA and EN would make the above call to return EN_CA but that is not going to solve the problem since it would cause a similar issue when calling the method for "EN".
Additional context related information: In my code, the LanguageType Enum is represent the index for a dictionary and these indices are used for localizing the language.
Does anyone have any idea of how to map two enum member to the same value while being able to get proper member from Enum.Parse? Do I just need to implement my own version of Enum.Parse which doesn't collapse the members with the same value into one?
An enum member is distinct from other enum members if and only if it has a different value. Effectively the members of the enumeration are named constants, with no real distinction between them other than the value they hold.
In your LanguageType enum you have two labels for the same value, and no way to distinguish them. Try this:
Console.WriteLine("{0} == {1} ? {2}",
LanguageType.EN.ToString(),
LanguageType.EN_CA.ToString(),
LanguageType.EN == LanguageType.EN_CA);
The output is:
EN == EN ? True
The same thing happens when you assign LanguageType.EN_CA to a variable, then examine the variable later to see what it contains. What you get is LanguageType.EN.
The key here is that the value of the member is all-important in most instances, with the position of the member being the tie-breaker during collisions. When two members have the same value the member that is declared first is the one that you will see whenever you do string conversions, including when you examine the value in the IDE.
So in effect you have a value LanguageType.EN_CA that is only an alias to the value LanguageType.EN.
While I can think of a couple of cute uses for this - like parsing incoming data that has multiple representations for the same value - it is really quite a terrible thing to do in most real-world environments, especially if you want to be able to do fully symmetric serialization/deserialization.
Now, as to your localization Dictionary...
It costs very little to store the same class object multiple times in a Dictionary, since class objects are stored by reference. Assuming you have a Localization class, the following code is not particularly inefficient in terms of storage:
enum LanguageType
{
EN, EN_CA, EN_US, EN_GB, EN_AU, FR
}
Dictionary<LanguageType, Localization> localizations = new Dictionary<LanguageType, Localization>();
localizations[LanguageType.EN] = new Localization("EN");
localizations[LanguageType.EN_CA] = localizations[LanguageType.EN];
localizations[LanguageType.EN_US] = localizations[LanguageType.EN];
localizations[LanguageType.EN_GB] = localizations[LanguageType.EN];
localizations[LanguageType.EN_AU] = localizations[LanguageType.EN];
Even if the Localization object contains a huge collection of resources, the above code only ever creates one instance of it. You get distinct values for the LanguageType members, and the Dictionary does the mappings for you.
You defined 0 twice in your enum - this will not work. Each value has to be unique or how else would an enum recognize its values - it is actually stored as integer.
Change it to:
enum LanguageType
{
EN = 0,
EN_CA = 1,
FR = 2
}
EDIT:
As pointed out by Greenish, you can define multiple names for the same value which acts as a sort of an alias. Using both or multiple names return the same value. If you try to get the string value from an integer value, you will get the first value defined for that integer.
In your case, you cannot achieve what you need using enums. You should probably build your own custom class to achieve that.
Enums basically are named integers. And it is possible to assign different names for a single number (as in your example for 0).
Enum.Parse searching for a first correct instance - and here you have a valid name as 0 == 0. So the solution is to change your numbers (or even just get rid of them as they are 0, 1, 2)
enum LanguageType
{
EN,
EN_CA,
FR
}
I thought of a way but it's messy fragile and naff. There again it illustrates the hole you have dug for yourself..
int index = Enum.GetNames(typeof(LanguageType)).indexof("EN_CA")
will give you 1
then something like
switch(index)
{
case 0 : return LanguageType.EN;
case 1 : return LangaugeType.EN_CA;
case 2 : return LanguageType.FR;
default : // throw some useful exception maybe
break
}
will return the member you want.
Horrible isn't it?
Enum.GetValues(typeof(LanguageType)) would return [0,0,1] and using indexof 0 on it is of course 0, which is why Parse is giving you the result it is.
The =0 specifies the representation of the enum's value in the underlying type (int). You've given both EN and EN_CA the same representation, namely 0, so now they've effectively become two labels for the same value.
Enum.Parse returns this value and it'll equal both labels.
The underlying problem is that you're trying to code a hierarchical concept, into a flat enum. For some purposes all english speaking cultures should be treated equal, for other purposes you'd like to distinguish between them.
The solution, I think, is to use the already present mechanisms for localizing your application, in particular CultureInfo should replace your enum and Resources your lookup dictionary.
I was a little surprised that this use of enum is allowed :)
But the MSDN documentation explicitly states it is valid and gives an example of how it can be useful:
enum Color
{
Red,
Green,
Blue,
Max = Blue
}
So here is how I fixed my problem:
I was not able to find a clean fix for the problem by getting Enum.Parse method return what I was expecting it to.(please see the note*)
My fix was to apply GroupBy(LanguageIndex) on the resulting dictionary which had its index duplicated and therefore throwing an exception. Since I wanted EN_CA and EN to have the same value in the enum that gave me what I was looking for without throwing an exception.
I can see that my fix is not an actual answer to the question that I initially asked, ignoring the context; though I though it might still be applicable to other contexts with a similar issue.
note* : I could have implemented my own version of Enum.Parse - Please see this answer for an alternative implementation - but that required me to put smelly hardcoded stuff into my code, so I just gave up on fixing the Parse method.
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?
My question is: can I check whether a variable (string or int/double type) or an array (string or int/double type) is initialized in C#?
Thanks in advance.
You are guaranteed some sort of initialization. For any static or instance members, all variables are automatically initialized when the type or instance is constructed, either explicitly or implicitly (in which case default(Type) is the value, so 0 for numeric types, null for strings and other reference types, etc.).
For local variables, they cannot be used before declaration, so if you can check it, it's been initialized.
Yes you can.
For types that require instances (string or arrays, as you asked), you can verify if they are null.
You could do this many ways but one way is :
if (myObject == null)
{
//initialize it here
}
Primitive data types do not require instancing. For example:
int i;
wont be equal to null, it will be equal to 0.
Try This, :
If var = NULL Then
MsgBox ('Not initialized')
End If
C# requires that all variables be initialized to some value before you read them.
The code block:
int i;
if(i == 0)
{
// something...
}
Will generate a compile-time error because you're trying to access the value of i before assigning it. This also applies to objects (although you can initialize them to null to begin with).
If you are wanting to know if you have modified from your initial assignment, then no, there is no way of telling that directly unless the initial assignment is to a sentinel value that will not be repeated by a subsequent assignment. If this is not the case you will need an extra bool to track.
No. However, you will have a compiler error if it is a local variable. If it is a class member then it is automatically initialized to the default (0 for ints, null for objects, etc.)
tongue in cheek, but accurate answer
Scan your source code and find all usages and declarations of the variable to verify that it is initialized either at declaration, or else somewhere guaranteed before using it.
Just curious.
If you go:
string myString;
Its value is null.
But if you go:
int myInt;
What is the value of this variable in C#?
Thanks
David
Firstly, note that this is only applicable for fields, not local variables - those can't be read until they've been assigned, at least within C#. In fact the CLR initializes stack frames to 0 if you have an appropriate flag set - which I believe it is by default. It's rarely observable though - you have to go through some grotty hacks.
The default value of int is 0 - and for any type, it's essentially the value represented by a bit pattern full of zeroes. For a value type this is the equivalent of calling the parameterless constructor, and for a reference type this is null.
Basically the CLR wipes the memory clean with zeroes.
This is also the value given by default(SomeType) for any type.
default of int is 0
The default value for int is 0.
See here for the full list of default values per type: http://msdn.microsoft.com/en-us/library/83fhsxwc.aspx
Here is a table of default values for value types in C#:
http://msdn.microsoft.com/en-us/library/83fhsxwc.aspx
Reference types default value is usually null.
String is a reference type. Int is a value type. Reference types are simply a pointer on the stack directed at the heap, which may or may not contain a value. A value type is just the value on the stack, but it must always be set to something.
The value for an unitialized variable of type T is always default(T). For all reference types this is null, and for the value types see the link that #Blorgbeard posted (or write some code to check it).
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.