Difficulties with dynamically identifying enum member - c#

public enum Levels
{
LevelState1 = 0,
LevelState2 = 1,
LevelState3 = 2
}
private Levels currentLevel;
public void ChooseLevel(Levels levelstate)
{
switch (levelstate)
{
case Levels.LevelState1:
currentLevel = Levels.LevelState1;
...
break;
case Levels.LevelState2:
currentLevel = Levels.LevelState2;
...
break;
case Levels.LevelState3:
currentLevel = Levels.LevelState3;
...
break;
}
}
//The variable CurrentLevel is an integer
ChooseLevel(Levels."LevelState"+game1.CurrentLevel.ToString());
I always get this error message in the last line:
Identifier expected
What should I change? I don't know how to fix this problem.

Either wrap this in a try/catch:
Levels level = (Levels)Enum.Parse(typeof(Levels),
"LevelState" + game1.CurrentLevel.ToString());
ChooseLevel(level);
Or use Enum.TryParse()

I feel that you are overcomplicating things. You can do this much simpler in a way similar to this:
public enum Levels
{
LevelState1 = 1,
LevelState2 = 2,
LevelState3 = 3
}
private Levels currentLevel;
public void ChooseLevel(int state)
{
currentLevel = (Levels)state; // casting to enum from int
// process level or whatever here
}
//The variable CurrentLevel is an integer
ChooseLevel(game1.CurrentLevel);
Since your CurrentLevel variable is an integer, you can easily cast it to your enum by binding level states to actual integer values within the level range. So instead of starting at 0 in your enum, you start at the first level value (which in your case is 1, no?).
Hope this helps.

ChooseLevel expectes enum argument, whereas you're using a mixture of enum and string, you'll have to parse it:
Levels game1Level = (Levels)Enum.Parse(typeof(Levels), "LevelState" + game1.CurrentLevel);
ChooseLevel(game1Level);
You can also use Enum.TryParse

Related

Getting an Enum member by its index (not the value assigned to it) in c#

in JavaScript world you can get an enum value according to its index in the object (not the value assigned to the enum member, but always the nth member of that enum):
const myEnum = {
Hello: 1,
Bye: 2,
Greeting: 3
}
const value = myEnum[Object.keys(myEnum)[0]];
console.log(value) // it returns 1
I was wondering if it's possible to have this kind of behavior in C# too.
I am trying to find the nth member of an Enum in C# and the values in it are all different and there is no order to them (and that's exactly how I want them to be).
Update
enum CSharpEnum {
SomeValue = 4,
AnotherValue = 2,
AndAnotherOne = 1
}
I get some indexes (like n) from somewhere else and I want to get the nth memeber of CSharpEnum. An example:
var index = 2;
var member // a way to get the member and it should return 1 (AndAnotherOne)
// because it is the third member (0, 1, 2)
Update 2
It seems my question is not clear enough so here is a link to a dotnetfiddle playground.
In one of the answers there was a GetValues method which made a list of enum values but the enum members got rearranged in it.
I have an enum in the playground and I want to get the third (0, 1, 2) member for example which is Want. Is there a way I can get that?
With enum
public enum Test
{
hello,
world
}
Create an array with
var enums = (Test[])Enum.GetValues(typeof(Test));
And now it's indexable.
Given
public enum myEnum
{
Hello = 1,
Bye = 2,
Greeting = 3
}
the Enum Class has a static method GetValues(Type) that returns an array TEnum[] of the values of this enum:
myEnum[] enumArray = (myEnum[])Enum.GetValues(typeof(myEnum));
myEnum value = enumArray[i]; // { [0] = Hello, [1] = Bye, [3] = Greeting }
Newer versions of the Framework have a generic overload (since .NET Framework 5.0?):
myEnum[] enumArray = Enum.GetValues<myEnum>();
myEnum value = enumArray[i];
UPDATE
The purpose of an enumeration type is to provide a set of named constants having an underlying integral numeric type. These constants are not indexed and have no particular order defined. If you want to have them indexed, insert them into an array
enum myEnum {
SomeValue = 4,
AnotherValue = 2,
AndAnotherOne = 1
}
static readonly myEnum[] enumArray = new[] {
myEnum.SomeValue,
myEnum.AnotherValue,
myEnum.AndAnotherOne
};
myEnum value = enumArray[2]; // --> myEnum.AndAnotherOne
See also: Enumeration types (C# reference)

How do I get a value within a class stored within an array?

I'm making a C# script in Unity. My intention is to create a class Scenario, create classes representing different scenarios, which would then be stored in an array scenarioListAll.
A (simplified) version of the code is as follows:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OverallManager2 : MonoBehaviour
{
public static object[] scenarioListAll = new object[40];
public class Scenario
{
    public string scenarioDesc;
    public bool surprise; // The 'surprise' bool I want to reference is defined here
public string surpriseType;
    public int[] leftOption;
    public int[] rightOption;
public int scenarioNumber;
public Scenario(string st, bool sp, int[] l, int[] r, int n)
{
scenarioDesc = st;
surprise = sp;
leftOption = l;
rightOption = r;
scenarioNumber = n;
}
// I haven't used this, but I'm not sure if this matters so I'm including this too
public Scenario(string st, bool sp, string spt, int[] l, int[] r, int n)
{
scenarioDesc = st;
surprise = sp;
surpriseType = spt;
leftOption = l;
rightOption = r;
scenarioNumber = n;
}
}
public static int[] getArray(int a, int b, int c, int d, int e, int f)
{
int[] arr = new int[6] {a, b, c, d, e, f};
return arr;
}
// Storing scenarios, am looking for the bool (2nd position)
public Scenario s1 = new Scenario("Test1", false, getArray(1, 1, 1, 1, 1, 1), getArray(1, 1, 1, 1, 1, 1), 1);
public Scenario s2 = new Scenario("Test2", true, getArray(1, 1, 1, 1, 1, 1), getArray(1, 1, 1, 1, 1, 1), 2);
public Scenario s3 = new Scenario("Test3", false, getArray(1, 1, 1, 1, 1, 1), getArray(1, 1, 1, 1, 1, 1), 3);
void Awake()
{
// Store scenarios in object array
scenarioListAll[0] = s1;
scenarioListAll[1] = s2;
scenarioListAll[2] = s3;
for(int i = 0; i < 40; i++)
{
object temp = scenarioListAll[i]; // Trying to extract the object stored in the array in a temp object
bool surpriseCheck = temp.surprise; // I am having problems with this line
if(surpriseCheck == true)
{
// Do something
}
}
}
// Ignoring start and update since they're irrelevant in this context
}
What I would like to do is to check whether the surprise element within a newly defined scenario (e.g. s1) is true. To do that, I was planning to extract the scenario stored in the array scenarioListAll, and then extract the surprise component from there. However, I'm couldn't figure out how to do this (e.g. in the code shown above, it returns Compiler Error CS1061).
I don't think I was able to find any documentation on this either, but I might not have understood something. I'm learning on my own so please bear with my poor knowledge/presentation.
Thank you for your time. Your help is much appreciated.
You are having a compilation issue due to the fact that the c# compiler doesn't know that temp is a Scenario since you declared it as "object". If you want to loop through the scenarios and check to see if they are a surprise you can use something like this:
foreach(Scenario temp in scenarioListAll)
{
bool surpriseCheck = temp.surprise;
if(surpriseCheck == true)
{
// Do something
}
}
Another way of accomplishing the same task with more control over the iteration would be:
for(int i = 0; i < scenarioListAll.Length; i++)
{
Scenario temp = scenarioListAll[i];
bool surpriseCheck = temp.surprise;
if(surpriseCheck == true)
{
// Do something
}
}
The benefit of the first version is that you don't have to worry about overrunning the bounds of the array. As Mike added below you could also use var to have the compiler fill in the type for you.
It's sometimes easiest to allow the compiler to determine the type of a variable for us.
In your case, you've specified that the variable temp will be of type object. Now, that's fine, but while a Scenario derives from object, and object is the lowest level class in the .Net environment, and is not a Scenario.
The var keyword doesn't mean that the declared type is of a "variable" type, instead it's telling the compiler just to "fill in" the correct type, based on the action you're taking. So, to put this in to action in your case, you could do this instead:
for( var i = 0; i < 40; i++ ) // notice the use of var here as well
{
var scenario = scenarioListAll[i]; // renamed temp to scenario
// var surpriseCheck = scenario .surprise; // var used but line not required
if( scenario.surprise )
{
// Do something
}
}
I went overboard there to demonstrate that the compiler is quite happy with the var keyword just about wherever you'd specify a data type as a type for a variable. Obviously not when you're trying to cast types, and there ARE sometimes where you'd want to specify the exact type you're trying to instantiate.
In your case, your next issue will be that you've defined the array as having 40 object elements, but you've then only instantiated 3 Scenario elements (which is valid, but probably not quite what you want overall). So your code, as it stands, is going to NullReference error out. You'll be able to avoid that, with a small modification, so your amended code could look like this, to include some type checks:
for( var i = 0; i < scenarioListAll.Length; i++ )
{
// First, check to see if the object in the array cell is a Scenario.
// If the item in the cell is a Scenario, check to see if surprise is set.
if ( scenarioListAll[i] is Scenario scenario && scenario.surprise )
{
// Do something
}
}
for more information on the is keyword, check the Microsoft Docs here.

C# constant list of values

I want control a other device with a C# program, this device have something like registers for read and write. So I searching something to enter all register numbers to get a better human readable code and to have central config place. All the registers using a uint value.
I searching something like this:
public enum EISCJoin : uint
{
Read_Connect = 1,
Read_Temp = 2,
Read_Switch = 3,
Write_Connect = 1,
Write_Temp = 2,
Write_Switch = 3,
}
switch (args.Sig.Number) //uint value
{
case (uint)EISC.Read_Connect:
{
args.SendValue[(uint)Write_Connect] = 1;
...
break;
}
case (uint)EISC.Read_Temp:
{
args.SendValue[(uint)Write_Temp] = 1;
...
break;
}
case (uint)EISC.Read_Switch:
{
args.SendValue[(uint)Write_Switch] = 1;
...
break;
}
}
My problem is that I don't want cast the ENUM value thousands of times in my source code and what I know is that a implicit conversation is not possible with enum.
Have someone a good idea to create a constant list of uint values?
you need to cast the number instead:
switch (args.Sig.Number)
to
switch ((EISCJoin)args.Sig.Number)
The other way is to use a static class and constant uints:
static public class EISCJoin
{
public const uint Read_Connect = 1;
public const uint Read_Temp = 2;
// and so on
}
I must work with a framework of the manufacturer and have no access to all the classes, it is not a option to modify all classes to the enum.
I using a value the most time only 1-2 times, so the most time I cast the value for 1 time use.
It looks like I must use the static class with the const uint variables.
Thanks for your help

How can I get the correct enum Value from an int c#

I have an int and I want to know the corresponding enum value.
Actually have an enum and I want to return the corresponding value for another enum.
I might just use a large switch but I would like to know if there is a better way.
Something like this?
MyEnum m = (MyEnum)((int)otherEnum);
var en = (StringSplitOptions)SeekOrigin.Begin;
How do the two enum types "correspond"? If there is no direct link, then yes, a large switch statement will be necessary. Otherwise, if they have the same underlying value, then you can simply cast from one type to the other. If you have an int, you can also cast that to the desired enum type.
There are two cases, one where the enums are sharing the values, and one when they are sharing the name. You can cast the values and parse the names as shown here. If neither the names nor the values are the same you of course can't do this.
public void Test() {
var one = FirstEnumWithSameValues.Two;
var two = (SecondEnumWithSameValues) one;
var three = FirstEnumWithSameName.Two.ToString();
var four = (SecondEnumWithSameName) Enum.Parse(typeof(SecondEnumWithSameName), three);
}
public enum FirstEnumWithSameValues
{
One = 1,
Two = 2,
Three = 3
}
public enum SecondEnumWithSameValues
{
Uno = 1,
Due = 2,
Trez = 3
}
public enum FirstEnumWithSameName
{
One = 1,
Two = 2,
Three = 3
}
public enum SecondEnumWithSameName
{
One = 4,
Two = 5,
Three = 6
}

enum name with multiple values

In my project i'm using enums example:
public enum NcStepType { Start = 1, Stop = 3, Normal = 2 }
i'm reading values from a database, but sometimes there are 0-values in my record, so i want an enum that looks like
public enum NcStepType { Start = 1 OR 0, Stop = 3, Normal = 2 }
is this possible (in c#) ?
You could create a generic extension method that handles unknown values:
public static T ToEnum<T>(this int value, T defaultValue)
{
if (Enum.IsDefined(typeof (T),value))
return (T) (object) value;
else
return defaultValue;
}
Then you can simply call:
int value = ...; // value to be read
NcStepType stepType = value.ToEnum(NcStepType.Start);
// if value is defined in the enum, the corresponding enum value will be returned
// if value is not found, the default is returned (NcStepType.Start)
No, basically. You would have to give it one of the values (presumably the 1), and interpret the other (0) manually.
No it is not, and I'm not sure how it would work in practice.
Can't you just add logic that maps 0 to 1 when reading from the DB?
Normally i define in such cases the 0 as follows:
public enum NcStepType
{
NotDefined = 0,
Start = 1,
Normal = 2,
Stop = 3,
}
And somewhere in code i would make an:
if(Step == NcStepType.NotDefined)
{
Step = NcStepType.Start;
}
This makes the code readable and everyone knows what happens... (hopefully)
No, in C# an enum can have only one value.
There's nothing that says the value in the database must map directly to your enum value however. You could very easily assign a value of Start whenever you read 0 or 1 from the database.
public enum NcStepType { Start = 1 | 0, Stop = 3, Normal = 2 }
No solution in C#. But you can take 2 steps:
1. Set default value of your DB field to 1.
2. Update all existing 0 to 1.
As far as I know you can write this
enum NcStepType { Start = 0, Start = 1, Stop = 3, Normal = 2 }
The only problem is later there would be no way telling which Start was used for variable initialization (it would always look like it was the Start = 0 one).

Categories