Increment an enumeration value to the next one - c#

I have an enumeration like so:
[Flags]
public enum UserProcessStage : uint
{
ShopSelection = 1,
FillBasket = 2,
SpecifyShipmentCredentials = 4,
SpecifyPaymentCredentials = 8,
OrderComplete = 16
}
Assuming I have a variable whose value is FillBakset (2), what I want to do is be able to increment it to the next value that is defined within the enumeration (SpecifyShipmentCredentials, 4).
The problem is that incrementing it causes its value to be 3 since it is based on an integer, I tried multipliying it by 2 but got a compilation error.
How could I increment an enumeration value to the next one ?
Thanks

You can use this code. It basically orders the enum by underlying value and then givs you the first enum which is bigger than the one specified. If none found, it will return 0 because of DefaultIfEmty():
public static UserProcessStage GetNext(UserProcessStage value)
{
return (from UserProcessStage val in Enum.GetValues(typeof (UserProcessStage))
where val > value
orderby val
select val).DefaultIfEmpty().First();
}

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)

Precedence of enum names

Given the following enum:
[Flags]
public enum Intervals
{
Root = PerfectUnison,
Unison = PerfectUnison,
PerfectUnison = 1 << 0,
AugmentedUnison = MinorSecond,
MinorSecond = 1 << 1,
Second = MajorSecond,
MajorSecond = 1 << 2,
AugmentedSecond = MinorThird,
MinorThird = 1 << 3,
Third = MajorThird,
MajorThird = 1 << 4,
AugmentedThird = PerfectFourth,
DoubleAugmentedThird = Triton,
DiminishedFourth = MajorThird,
Fourth = PerfectFourth,
PerfectFourth = 1 << 5,
AugmentedFourth = Triton,
DoubleAugmentedFourth = PerfectFifth,
Triton = 1 << 6,
//...Removed for brevity, see link to code bellow
}
I'm trying this simple test:
static void Main(string[] args)
{
var values = Enum.GetValues(typeof(Intervals));
foreach (var value in values)
{
Console.WriteLine(value);
}
}
And here is the output:
PerfectUnison, PerfectUnison, PerfectUnison, AugmentedUnison, AugmentedUnison, Second, Second, MinorThird, MinorThird, DiminishedFourth, DiminishedFourth, DiminishedFourth, AugmentedThird, AugmentedThird, AugmentedThird, AugmentedThird, DoubleDiminishedSixth, DoubleDiminishedSixth etc.
While I want the enum names selected for identical values to be of the following sequence:
Root, MinorSecond, Second, MinorThird, Third, Fourth, Triton, Fifth, MinorSixth, Sixth, MinorSeventh, Seventh, Octave, MinorNinth, Ninth, Tenth, Eleventh, MajorEleventh, Thirteen
A good reproduction would also be Enum.GetNames. I want the names of the above group should always precede their value-matching names.
I'm basically looking for a documentation of the rules of precedence/priority of enum names per value.
You can play around with the code here: http://rextester.com/EJOWK87857.
Update
I'm now looking into decompiled Enum.GetNames. Looks like it uses reflection. So the question is then, "How to control the order of reflected fields?".
Without using metadata, this is not possible since the compiler may assign the constant value to each enum member. Examining the compiled IL shows that the assignment information is lost when the code is compiled:
.field public static literal valuetype .../Intervals Unison = int32(1)
.field public static literal valuetype .../Intervals PerfectUnison = int32(1)
.field public static literal valuetype .../Intervals AugmentedUnison = int32(2)
...
Since this information is lost when the source is compiled (or, at least, is not guaranteed to be available), it would not be possible to assign priority rules based on assignment at runtime. This limitation is consistent with the documentation for Enum.ToString(), which states that if multiple names are associated with the same value, the member chosen is nondeterministic:
If multiple enumeration members have the same underlying value and you attempt to retrieve the string representation of an enumeration member's name based on its underlying value, your code should not make any assumptions about which name the method will return.
This said, a possible workaround may be to assign attribute values to the enum values that are deemed to be a priority on assignment. For instance:
[AttributeUsage(AttributeTargets.Field)]
class PriorityAttribute : Attribute { }
[Flags]
public enum Intervals
{
Root = PerfectUnison,
Unison = PerfectUnison,
[Priority]
PerfectUnison = 1 << 0,
AugmentedUnison = MinorSecond,
[Priority]
MinorSecond = 1 << 1,
Second = MajorSecond,
[Priority]
MajorSecond = 1 << 2,
AugmentedSecond = MinorThird,
...
Since the attribute information is associated with the enum values at runtime, the marked enumeration names can be accessed at runtime:
typeof(Intervals)
.GetFields()
.Where(a => a.GetCustomAttributes(typeof(PriorityAttribute), false).Length > 0)
.Select(a => a.Name))
Likewise, you can write an analogue to Enum.GetName to return only the names with the attribute defined (e.g., GetPriorityName(typeof(Intervals), 1) will always return PerfectUnison.
static string GetPriorityName(Type enumType, object v)
{
Type ut = Enum.GetUnderlyingType(enumType);
var pty = enumType.GetFields()
.Where(
a => a.IsLiteral
&& a.GetRawConstantValue().Equals(v)
&& a.GetCustomAttributes(typeof(PriorityAttribute), false).Length > 0
)
.FirstOrDefault();
if (pty == null)
return Enum.GetName(enumType, v); // default to standard if no priority defined
return pty.Name;
}

Is there a better way to check for valid values?

I have a property in my class that can only be one of several values, what is the best way to limit the input on this property.
Here is what I'm doing now, and I'm sure there must be a better way.
public void SetValue(int value)
{
if(value != 1 ||
value != 4 ||
value != 8 ||
value != 16 ||
value != 32 ||
value != 64, ||
value != 128)
{
property_value = 1;
}
else
{
property_value = value;
}
}
Instead of in int, use an Enum with these values.
I am sure each value has a specific meaning - expose these as enum members.
This may not eliminate all issues (since an Enum is simply a wrapper over an integer type and can still get assigned a value that doesn't exist in the enumeration), but should take care of most problems, so long as you are consistent about only passing values from the enumeration itself.
In any rate, you can then simply test the passed in value against the enumeration and throw an exception if it isn't a valid member.
Use enum instead of this numeric values like:
enum Numbers { Name1 = 1, Name2 = 4 ... }
and then you can easilly check if value is one of enum element:
Enum.IsDefined(typeof(Numbers), value );
For your example, you can just do:
property_value = 1;
since your if condition will always be true.
If you want to restrict it to a number of possibilities you could:
Declare an enum:
public enum Value
{
Default = 1,
Option1 = 4,
...
}
or have a collection of valid values to check:
int[] validValues = new int[] { 1, 4, 8, 16, 32, 64, 128 };
property_value = validValues.Contains(value) ? value : 1;
Although I would prefer to throw an exception on invalid input.
I think you should consider using an enum:
public enum MyEnum
{
These,
Are,
Valid,
Values
}
public void SetValue(MyEnum _value)
{
// Only MyEnum values allowed here!
}
if(((value & (value − 1)) == 0) && value != 2 && value <= 128)
property_value = 1;
else
property_value = value;
(value & (value − 1)) is a fast way to check if value is a power of two.
As an example: value = 4:
(4(10) & (3(10)) =
100(2) & 011(2) =
000(2) = 0
value = 5
(5(10) & (4(10)) =
101(2) & 100(2) =
100(2) =
4
You could use an enum and check using Enum.IsDefined(value). But then you'd have to think of a (meaningfull) name for all the possible values.
I think we're missing the INTENT of the function here.
It looks like a bit mask check to me. If that's the case, he's missing 2 from the code sample. Also, note that he's not discarding a value if it isn't one of those specific bits: he preserves it. If it is a value equal to a specific bit (and only that bit) he coerces it to 1.
I think the sample provided by Lee works best in this case; it's simple and to the point. Also, if the check is widened to account for 16 bits (or even 32), it will easily catch them all.

Testing a [Flags] enum value for a single value

If I have an enum that's marked with [Flags], is there a way in .NET to test a value of this type to see if it only contains a single value? I can get the result I want using bit-counting, but I'd rather use built-in functions if possible.
When looping through the enum values dynamically, Enum.GetValues() returns the combination flags as well. Calling that function on the enum in the following example returns 4 values. However, I don't want the value combinations included in the inner algorithm. Testing individual enum values for equality is out, since the enum could potentially contain many values, and it also requires extra maintenance when the values in the enum change.
[Flags]
enum MyEnum
{
One = 1,
Two = 2,
Four = 4,
Seven = One | Two | Four,
}
void MyFunction()
{
foreach (MyEnum enumValue in Enum.GetValues(typeof(MyEnum)))
{
if (!_HasSingleValue(enumValue)) continue;
// Guaranteed that enumValue is either One, Two, or Four
}
}
private bool _HasSingleValue(MyEnum value)
{
// ???
}
Related: StackOverflow: Enum.IsDefined on combined flags
You can cast it to int and use the techniques from Bit Twiddling Hacks to check if it's a power of two.
int v = (int)enumValue;
return v != 0 && (v & (v - 1)) == 0;
You can use a combination of IsDefined and checking for powers of 2.
You could you Enum.GetValues and count only those items that are a power of 2 (evenly divisible by 2 with no remainder).

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