Can i keep instances of class inside enum? - c#

Everywhere i meet enums with string as a value and int as an index, but what if i want to keep instances inside enum like this:
public enum TestEnum
{
new Person("John"),
new Person("Jack")
}
Is it possible?
Just asking
//Edit 2019: I was so stupid then, should have used as a array

This can't be done.
An enum type is a distinct value type (§4.1) that declares a set of named constants.
The body of an enum type declaration defines zero or more enum members, which are the named constants of the enum type. No two enum members can have the same name.
Each enum member has an associated constant value. The type of this value is the underlying type for the containing enum. The constant value for each enum member must be in the range of the underlying type for the enum.
Enums have members that are named constants and an associated constant value. Each Enum also has an underlying type, which defaults to int. The constant values can be given explicitly, or they can be implicit.
enum Color
{
Red,
Blue,
Green
}
is equivalent to
enum Color : int
{
Red = 0,
Blue = 1,
Green = 2
}
A class instance, such as new Person("Jack"); is not a constant, and not valid as an enum member or value.
Beyond just the validity of trying to do this, I'm not certain how you would expect this to be used. Are you looking to be able to access a TestEnum.Jack and retrieve your Person("Jack") instance? If so, you could accomplish something similar to this with a class that has static readonly properties with the correct defaults provided.
public static class People {
public static Person Jack {get;} = new Person("Jack");
public static Person John {get;} = new Person("John");
}
You can now get your person instances with People.John and People.Jack.
This can lead into issues if the Person class is mutable, despite these properties being readonly.

Related

Why does C# not warning about non-nullable long field?

Why do I not get a non-nullable warning (or some other warning) for FieldTwo not being set in the constructor? I'm using .Net 5.0 and Nullable option is set to true in the project file.
public class MyClass
{
public string FieldOne;
public long FieldTwo;
public MyClass (string p1, long p2)
{
FieldOne = p1;
// FieldTwo is not set. Where is the non-nullable warning!?
}
}
long is a value type and cannot be null. So there is no reason for warn about null. What I suspect you want is a field not initialized warning.
If a private field is never assigned, it causes a CS0649 warning. However, if the field public, or is modified anywhere in the class, this warning is not raised. For example, the following would be perfectly acceptable code, and should not give a warning:
public class MyClass{
private long myLong;
public void Increment() => myLong++;
}
If the field should only be set from the constructor you should declare it as readonly. However, public readonly fields does not trigger a warning, even if they probably should. See Why do I NOT get warnings about uninitialized readonly fields?.
long is a value type and can't be null. Value types are always initialized when declared with a default value, in this case 0. You'd have to change the field type to long? if you wanted to store a null
Those fields aren't properties anyway. This isn't just semantics. Fields are implementation details, even public fields. They aren't considered part of a class's API surface. Properties are part of the API, they get serialized by default by all serializers (fields don't) and guarantee In fact having public fields is a code smell.
To ensure all properties are initialized you can use a record type instead of a class :
public record(string PropertyOne, long PropertyTwo);
This generates a class with init-only properties for PropertyOne and PropertyTwo and a constructor that requires values for all properties. Along with equality operators, deconstructors and a ToString() implementation that returns all properties in the form of a JSON string.

Pass a dropdown index value as value for an enum field

I have a panel with a dropdown; which I use to set a field in my project.
public class projectclass
{
public enum mainpriority
{
basic,
urgent,
critical
};
public mainpriority _priorityfield { get; set;}
}
The project class use an enum for this field, so to populate the dropdown I do this, to populate it:
mydropdown.options.Clear();
foreach (projectclass._priorityfield priority in projectclass._priorityfield.GetValues(typeof(projectclass._priorityfield)))
{
mydropdown.options.Add( new Dropdown.OptionData() {text = priority.ToString()});
}
This allow me to display the field in the dropbox, for each instance of the projectclass.
All is good in this direction, but if I want to do the opposite (change the value in the dropdown, and change the class field accordingly), I can't make it work.
The main issue is that I try to assign to the class, the value as int (which is what I get back from the dropdown.value() method), but VS tell me that it is not possible to set a _priorityfield type with an int type.
Isn't the enum, equivalent to 0,1,2.....n; so you can either use "basic" or 0 as value?
This is what I do to set the class instance value, from the dropdown, using the onValueChanged delegate
private void UpdatePriority(Dropdown priority)
{
int tempvalue = priority.value;
projectclass_instance1._priorityfield = tempvalue;
}
I assumed that I can pass an int, but VS says that is not possible. I could map each value of the dropdown to an entry in the enum, but I am not sure that it is actually the best solution.
Thanks to Ehsan for the solution.
The error is because I need to cast the int value as enum type, so the value will be correctly recognized.

Enum type in constructor

So I have to initiate an object from a class into the main form, but the arguments I have to put in the constructor are from an enum type I made in that class.
private List<Geluidsfragment> fragmenten;
private enum ThemaSoorten
{
Muziek,
Luisterboeken,
Cabaretshows
}
^this part is now outside the class, as was advised.
// Constrcutors
public BGExperience(ThemaSoorten thema)
{
fragmenten = new List<Geluidsfragment>();
this.thema = thema;
}
These are the fields and constructor for the field. Below is the initiation of the object of this class I need.
public GeluidsfragmentForm()
{
InitializeComponent();
BGExperience bgExperience = new BGExperience("Muziek");
}
So the overload has to be of the type ThemaSoorten and it has to be in the enum, but at this point it gets stuck.
Anyone know how to solve this?
You should make first your enum to be public and then try this one:
BGExperience bgExperience = new BGExperience(BGExperience.ThemaSoorten.Muziek);
If you don't make your enum to be public, you will not be able to access it outside your class let alone to create an instance of your class.
Update
As correctly Sriram has already pointed out in his comments, it would be a better design approach to not make this enum to be a nested type. You could declare it outside of your class, like:
public enum ThemaSoorten
{
Muziek,
Luisterboeken,
Cabaretshows
}
and then create a new BGExperience object as below:
var bgExperience = new BGExperience(ThemaSoorten.Muziek);
Important Note (thanks Selman22)
You can't declare an enum with the way you have already done it. This couldn't even compile. Furthermore, you should take an error message while you were typing this. Anyway, the correct way of defininit an enum is the following:
public enum EnumName
{
Member1,
Member2,
Member3
}
In place of EnumName you should put the name of your enum and in place of Member1, Member2 and Member3 the names of the items in your enum. If you want this items have specific values, you should do it like:
public enum EnumName
{
Member1 = 1,
Member2 = 2,
Member3 = 3
}
Or perhaps you want to provide string value of the enum to the constructor, then here is how it will work:
BGExperience bgExperience = new BGExperience((BGExperience.ThemaSoorten)Enum.Parse(typeof(BGExperience.ThemaSoorten), "Muziek"));
Make sure to make the enum public for that. Otherwise you have to provide string in the constructor and parsing it to the enum value within the constructor.
BGExperience bgExperience = new BGExperience(ThemaSoorten.thema1);

Setting enum value at runtime in C#

Is there any way that I can change enum values at run-time?
e.g I have following type
enum MyType
{
TypeOne, //=5 at runtime
TypeTwo //=3 at runtime
}
I want at runtime set 5 to TypeOne and 3 to TypeTwo.
As others have pointed out, the answer is no.
You could however probably refactor your code to use a class instead:
public sealed class MyType
{
public int TypeOne { get; set; }
public int TypeTwo { get; set; }
}
...
var myType = new MyType { TypeOne = 5, TypeTwo = 3 };
or variations on that theme.
Just refer to MSDN help HERE
An enumeration type (also named an enumeration or an enum) provides an efficient way to define a set of named integral constants that may be assigned to a variable.
Also HERE
In the Robust Programming Section - Just as with any constant, all references to the individual values of an enum are converted to numeric literals at compile time.
So you need to realign your idea of Enum and use it accordingly.
To answer your question - No it is not possible.
Enums are compiled as constant static fields, their values are compiled into you assembly, so no, it's not possible to change them. (Their constant values may even be compiled into places where you reference them.)
Eg take this enum:
enum foo
{
Value = 3
}
Then you can get the field and its information like this:
var field = typeof(foo).GetField("Value", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
Console.WriteLine(field.GetValue(null));
Console.WriteLine(field.Attributes);

As per CA1008 rule of FXCop Enums should have a default value of zero. Is this applicable for C#?

Should this rule be applicable to C#?
The compiler gives error "Use of unassigned local variable" if we try to use the enum without explicitly setting a value?
The perspective being asked is the validity of the FxCop rule since I cannot use the default value of an enum.
public enum TraceLevel
{
Off = 0,
Error = 1,
Warning = 2,
Info = 3,
Verbose = 4
}
class Program
{
static void Main(string[] args)
{
TraceLevel traceLevelOptions;
Console.WriteLine(traceLevelOptions.ToString());
Console.ReadLine();
}
}
Updated after getting the right answer. The following code should work:
public class SerializeMe
{
public int Id { get; set; }
public TraceLevel MyTrace { get; set; }
}
public enum TraceLevel
{
Off = 0,
Error = 1,
Warning = 2,
Info = 3,
Verbose = 4
}
class Program
{
static void Main(string[] args)
{
SerializeMe serializeMe = new SerializeMe();
Console.WriteLine(serializeMe.MyTrace.ToString());
Console.ReadLine();
}
}
The reason that enums should have a zero value is explained in the documentation for the Code Analysis error that relates to it:
http://msdn.microsoft.com/en-us/library/ms182149.aspx
CA1008: Enums should have zero value
The default value of an uninitialized enumeration, just like other value types, is zero. A non-flags−attributed enumeration should define a member that has the value of zero so that the default value is a valid value of the enumeration.
So the reason is that if, for example, you declare an enum field in a class or struct and do not initialise it, it will have the default value of zero. If there is no member of the enum with a zero value, you will in that (fairly common) situation have a enum field containing an invalid value.
There are also other instances where you can end up with a default-initialised enum field (e.g. during deserialization). You want to avoid a default-initialised enum field having an invalid value, hence the rule.
This isn't a FXCop error, it is a C# compiler error. In C# all the local variables must be initialized before being used.
TraceLevel traceLevelOptions = 0; // or TraceLevel.Error for example
Like for all the other types... If traceLevelOptions was an int, you would get the same error.
There is a loophole for struct types. You can assign them with a value or assign all their fields with a value, and they will be considered assigned. Note that this condition sometimes can't be satisfied if the struct has, for example, private fields.

Categories