Check if variable corresponds with Enum - c#

Say I have int val = 1; What is the best way to check whether or not that value corresponds with an enum. Here is a sample enum:
public enum AlertType
{
Success=1,
Warning=2,
Error=3
};
I'm looking for an answer that has the best maintainability.

I think you are looking for Enum::IsDefined Method
Returns an indication whether a constant with a specified value exists
in a specified enumeration.
Updated:-
Try something like this:-
if(Enum.IsDefined(typeof(AlertType), val)) {}

This should work:
Int32 val = 1;
if (Enum.GetValues(typeof(AlertType)).Cast<Int32>().Contains(val))
{
}

You can cast you enum choices to an int for that check :
const int val = 1;
if (val == (int)AlertType.Success)
{
// Do stuff
}
else if (val == (int) AlertType.Warning)
{
// Do stuff
}
else if (val == (int) AlertType.Error)
{
// Do stuff
}

In addition to the other solutions offered, here's another easy way to check:
Enum.GetName(typeof(AlertType), (AlertType)val) != null

if (Enum.IsDefined(typeof(AlertType), x))
{
var enumVal = Enum.Parse(typeof(AlertType), x.ToString());
}
else
{
//Value not defined
}

Related

Is there an easier way to parse an int to a generic Flags enum?

I've got a generic function to parse an object into a generic Enum.
However, I'm running into an issue when trying to safely parse an int into a [Flags] Enum.
Directly using Enum.ToObject() works to parse valid combinations, but will just return the original value if there isn't a flag combination.
Additionally, when there's no explicit enum member for a combination of flags, Enum.ToName() and Enum.IsDefined() don't return helpful values.
For Example:
[Flags]
public enum Color
{
None = 0,
Red = 1,
Green = 2,
Blue = 4,
}
// Returns 20
Enum.ToObject(typeof(Color), 20)
// Returns ""
Enum.ToName(typeof(Color), 3)
// Returns false
Enum.IsDefined(typeof(Color), 3)
I've written a function that I think technically works, but it seems like there has to be a better way to do this.
My Function:
public static T ParseEnumerator<T>(object parseVal, T defaultVal) where T : struct, IConvertible
{
Type ttype = typeof(T);
if (!ttype.IsEnum)
{
throw new ArgumentException("T must be an enumerated type");
}
bool isFlag = ttype.GetCustomAttribute(typeof(FlagsAttribute)) != null;
try
{
if (parseVal == null)
{
return defaultVal;
}
else if (parseVal is T)
{
return (T)parseVal;
}
else if (parseVal is string)
{
return (T)Enum.Parse(ttype, parseVal.ToString(), true);
}
//**************** The section at issue **********************************/
else if (isFlag && parseVal is int)
{
List<string> flagsList = new List<string>();
int maxVal = 0;
//Loop through each bit flag
foreach (var val in Enum.GetValues(ttype))
{
if (CountBits((int)val) == 1)
{
if ((int)val > maxVal)
maxVal = (int)val;
// If the current bit is set, add the flag to the result
if (((int)parseVal & (int)val) == (int)val)
{
string enumName = Enum.GetName(ttype, val);
if (!string.IsNullOrEmpty(enumName))
flagsList.Add(enumName);
}
}
}
// Is the value being parsed over the highest bitwise value?
if ((int)parseVal >= (maxVal << 1))
return defaultVal;
else
return (T)Enum.Parse(ttype, string.Join(",", flagsList));
}
//************************************************************************/
else
{
string val = Enum.GetName(ttype, parseVal);
if (!string.IsNullOrEmpty(val))
return (T)Enum.ToObject(ttype, parseVal);
else
return defaultVal;
}
}
catch
{
return defaultVal;
}
}
Is there something I'm missing? Or is there another way to parse these values safely?
Any help is appreciated, thanks!
-MM
Since your generic function has to know the Enum type to begin with, you can just scrap the function and use basic casting instead.
using System;
namespace SO_58455415_enum_parsing {
[Flags]
public enum CheeseCharacteristics {
Yellow = 1,
Mouldy = 2,
Soft = 4,
Holed = 8
}
public static class Program {
static void Main(string[] args) {
CheeseCharacteristics cc = (CheeseCharacteristics)12;
Console.WriteLine(cc);
}
}
}
If all you want to know is if you have a value that can be created using the enum flags.. that's pretty easy, as long as we can assume that each flag is "sequential" (e.g. there are no gaps between the flags). All numbers between 1 and the sum of all flag values can be made by some combination of flags. You can simply sum the flag values together and compare that to your question value.
public static bool IsValidFlags<T>(int checkValue) where T:Enum {
int maxFlagValue = ((int[])Enum.GetValues(typeof(T))).Sum();
return (0 < checkValue) && (checkValue <= maxFlagValue);
}
For future reference, you can constrain your generic parameter to an enum:
void fx<T> () where T:Enum { }

How to validate decimal places

Please let me know good way to validate decimal value, if decimal(4,2) it should accept 2 numeric and 2 decimal places.
var value = "44.29";
var dec = value.Split('.');
Then finding the length will can be used, I need a better culture specific way. I need a generic solution which can be applied to all decimal field.
Like:
validate(int before,int afterdecimal);
var valid = validate(2,2);
Need a generic cleaner solution for this
private static bool IsDecimal(string value, int before, int after)
{
if (value.Contains("."))
{
var parts = value.Split('.');
if (parts[0].Length == before && parts[1].Length == after)
return true;
}
else if(value.Length == before)
return false;
return true;
}
You can try like this:
[RegularExpression(#"^\d{1,2}(\.\d{0,2})$",ErrorMessage = "Value contains more than 2 decimal places")]
public decimal Value { get; set; }
If you whant just validate, try to use the mod:
44.29 % 1 = 0.29
From the above answers I was able to do it like this
string value = "2009.99";
if (IsDecimal(value, 4, 4))
{
Console.WriteLine("Valid");
}
private static bool IsDecimal(string value, int before, int after)
{
var r = new Regex(#"^\d{1," + before + #"}(\.\d{0," + after + #"})$");
return r.IsMatch(value);
}

How to cast string to int

I have a set of objects named something like this:
_1,_2,_3 .... _n
Isn't an array, just a bunch of objects uinto a custom control. I want to cast the name to an int. first I remove _, but If use
private void Superficie_MouseDown(object sender, MouseButtonEventArgs e)
{
int index = 0;
Shape myShape = ((Shape)sender);
string lcNombre = myShape.Name.Remove(0, 1);
//--------------------------------------------------------------------
// Those are my tryes
// Doesn't work because it must expect a nullable value
index = lcNombre as decimal;
// Doesn't work Can't convert string to int
index = (int)lcNombre;
//--------------------------------------------------------------------
if (index > 0)
{
bool lIsSelected = !Pieza.Superficies.Where(x=>x.Id == index).First().IsSelected;
Pieza.Superficies.Where(x => x.Id == index).First().IsSelected = lIsSelected;
if (lIsSelected)
myShape.Fill = new SolidColorBrush(SystemColors.HotTrackColor);
else
myShape.Fill = new SolidColorBrush(SystemColors.ControlLightLightColor);
}
}
How can I do to cast it ?
The most straightforward way is
index = int.Parse(lcNombre);
If you're not completely sure whether lcNombre is really an integer, you can use instead
int result;
bool isInt = int.TryParse(lcNobre, out result);
or in newer versions of .NET, you can declare the output variable like:
bool isInt = int.TryParse(lcNobre, out var result);
Finally you can use
index = Convert.ToInt32(lcNobre);
This approach (like int.Parse()) will throw a FormatException if the input value is not convertible to an integer.
You can also use the Convert static methods:
index = Convert.ToInt32(lcNombre);
MSDN Link: http://msdn.microsoft.com/en-us/library/sf1aw27b(v=vs.110).aspx
Error wise.. you may want to use TryParse.. as it returns true or false depending on a successful conversion:
int index;
if (int.TryParse(lcNombre, out index)) {
// conversion successful
}
else {
// couldn't convert
}
MSDN Link for int.TryParse: http://msdn.microsoft.com/en-us/library/f02979c7(v=vs.110).aspx
try this
int result=0;
Int32.TryParse(lcNombre,out result);
My favorite way to do this is to make an extension method as follows
public static class ExtensionMethods
{
public static int? AsInteger( this string str)
{
int value;
if ( int.TryParse( str, out value ) )
{
return value;
}
else
{
return null;
}
}
}
then you can this
index = lcNombre.AsInteger() ?? 0;
string strArr[] = myShape.Name.Split('_',StringSplitOptions.RemoveEmptyEntries)
int num;
int.TryParse(strArr[0],num);

A shorter way to write the following function in C#?

I have this function -
public int GetAvgResult()
{
var weeklyvalues=GetWeeklyValues();//gets list of weekly values.
if (weeklyvalues.Count == 0)
return 0;
return (weeklyvalues.Sum() / weeklyvalues.Count);
}
Is there a shorter way to write this using ?: or maybe something else ?
public double GetAvgResult()
{
// Assumes GetWeeklyValues() never returns null.
return GetWeeklyValues().DefaultIfEmpty().Average();
}
Do note that this returns a double , which I assume is what you really want (the average of a bunch of integers is logically not an integer). You can cast it to int if necessary, or if you want to stick with integer math all the way:
var seq = GetWeeklyValues().DefaultIfEmpty();
return seq.Sum() / seq.Count();
public int GetAvgResult()
{
var weeklyvalues = GetWeeklyValues();
return (weeklyvalues.Count != 0) ? (weeklyvalues.Sum() / weeklyvalues.Count) : 0;
}
or:
public int GetAvgResult()
{
return GetWeeklyValues().DefaultIfEmpty().Average();
}
public int GetAvgResult()
{
var weeklyvalues = GetWeeklyValues(); //gets list of weekly values.
return weeklyvalues.Count == 0 ? 0 : weeklyvalues.Sum() / weeklyvalues.Count;
}
That's as short as I'd attempt to make it. Is there a specific reason (other than code golf) you're trying for a low character count?
public int GetAvgResult()
{
var weeklyvalues = GetWeeklyValues();//gets list of weekly values.
return (weeklyvalues.Count == 0) ? 0 : (weeklyvalues.Sum() / weeklyvalues.Count );
}
public int GetAvgResult()
{
var weeklyvalues=GetWeeklyValues();//gets list of weekly values.
return weeklyvalues.Count == 0
? 0
: (weeklyvalues.Sum() / weeklyvalues.Count);
}

How to get next (or previous) enum value in C#

I have an enum which is defined like this:
public enum eRat { A = 0, B=3, C=5, D=8 };
So given value eRat.B, I want to get the next one which is eRat.C
The solution I see is (without range checking)
Array a = Enum.GetValues(typeof(eRat));
int i=0 ;
for (i = 0; i < a.GetLength(); i++)
{
if (a.GetValue(i) == eRat.B)
break;
}
return (eRat)a.GetValue(i+1):
Now that is too much complexity, for something that simple. Do you know any better solution?? Something like eRat.B+1 or Enum.Next(Erat.B)?
Thanks
Thanks to everybody for your answers and feedback. I was surprised to get so many of them. Looking at them and using some of the ideas, I came up with this solution, which works best for me:
public static class Extensions
{
public static T Next<T>(this T src) where T : struct
{
if (!typeof(T).IsEnum) throw new ArgumentException(String.Format("Argument {0} is not an Enum", typeof(T).FullName));
T[] Arr = (T[])Enum.GetValues(src.GetType());
int j = Array.IndexOf<T>(Arr, src) + 1;
return (Arr.Length==j) ? Arr[0] : Arr[j];
}
}
The beauty of this approach, that it is simple and universal to use. Implemented as generic extension method, you can call it on any enum this way:
return eRat.B.Next();
Notice, I am using generalized extension method, thus I don't need to specify type upon call, just .Next().
Probably a bit overkill, but:
eRat value = eRat.B;
eRat nextValue = Enum.GetValues(typeof(eRat)).Cast<eRat>()
.SkipWhile(e => e != value).Skip(1).First();
or if you want the first that is numerically bigger:
eRat nextValue = Enum.GetValues(typeof(eRat)).Cast<eRat>()
.First(e => (int)e > (int)value);
or for the next bigger numerically (doing the sort ourselves):
eRat nextValue = Enum.GetValues(typeof(eRat)).Cast<eRat>()
.Where(e => (int)e > (int)value).OrderBy(e => e).First();
Hey, with LINQ as your hammer, the world is full of nails ;-p
Do you really need to generalize this problem? Can you just do this instead?
public void SomeMethod(MyEnum myEnum)
{
MyEnum? nextMyEnum = myEnum.Next();
if (nextMyEnum.HasValue)
{
...
}
}
public static MyEnum? Next(this MyEnum myEnum)
{
switch (myEnum)
{
case MyEnum.A:
return MyEnum.B;
case MyEnum.B:
return MyEnum.C;
case MyEnum.C:
return MyEnum.D;
default:
return null;
}
}
The problem you're dealing with is because you're trying to get an enum to do something it shouldn't. They're supposed to be type safe. Assigning integral values to an enum is allowed so that you can combine them, but if you want them to represent integral values, use classes or structs. Here's a possible alternative:
public static class eRat
{
public static readonly eRatValue A;
public static readonly eRatValue B;
public static readonly eRatValue C;
public static readonly eRatValue D;
static eRat()
{
D = new eRatValue(8, null);
C = new eRatValue(5, D);
B = new eRatValue(3, C);
A = new eRatValue(0, B);
}
#region Nested type: ERatValue
public class eRatValue
{
private readonly eRatValue next;
private readonly int value;
public eRatValue(int value, eRatValue next)
{
this.value = value;
this.next = next;
}
public int Value
{
get { return value; }
}
public eRatValue Next
{
get { return next; }
}
public static implicit operator int(eRatValue eRatValue)
{
return eRatValue.Value;
}
}
#endregion
}
This allows you to do this:
int something = eRat.A + eRat.B;
and this
eRat.eRatValue current = eRat.A;
while (current != null)
{
Console.WriteLine(current.Value);
current = current.Next;
}
You really should only be using enums when you can benefit from their type safety. If you're relying on them to represent a type, switch to constants or to classes.
EDIT
I would suggest you take a look at the MSDN page on Enumeration Design. The first best practice is:
Do use an enumeration to strongly type
parameters, properties, and return
values that represent sets of values.
I try not to argue dogma, so I won't, but here's the problem you're going to face. Microsoft doesn't want you to do what you are trying to do. They explicitly ask you not to do what you are trying to do. The make it hard for you to do what you are trying to do. In order to accomplish what you are trying to do, you have to build utility code to force it to appear to work.
You have called your solution elegant more than once, and it might be if enums were designed in a different way, but since enums are what they are, your solution isn't elegant. I think that chamber music is elegant, but if the musicians didn't have the proper instruments and had to play Vivaldi with sawblades and jugs, it would no longer be elegant, regardless of how capable they were as musicians, or how good the music was on paper.
Works up to "C" since there is no answer on what to return after "D".
[update1]: Updated according to Marc Gravell's suggestion.
[update2]: Updated according to how husayt's wanted - return "A" for the next value of "D".
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Next enum of A = {0}", eRatEnumHelper.GetNextEnumValueOf(eRat.A));
Console.WriteLine("Next enum of B = {0}", eRatEnumHelper.GetNextEnumValueOf(eRat.B));
Console.WriteLine("Next enum of C = {0}", eRatEnumHelper.GetNextEnumValueOf(eRat.C));
}
}
public enum eRat { A = 0, B = 3, C = 5, D = 8 };
public class eRatEnumHelper
{
public static eRat GetNextEnumValueOf(eRat value)
{
return (from eRat val in Enum.GetValues(typeof (eRat))
where val > value
orderby val
select val).DefaultIfEmpty().First();
}
}
Result
Next enum of A = B
Next enum of B = C
Next enum of C = D
Next enum of D = A
Thanks you all, for your inspiration and solutions.
Here are my results, as an extension.
using System;
using System.Linq;
public static class Enums
{
public static T Next<T>(this T v) where T : struct
{
return Enum.GetValues(v.GetType()).Cast<T>().Concat(new[] { default(T) }).SkipWhile(e => !v.Equals(e)).Skip(1).First();
}
public static T Previous<T>(this T v) where T : struct
{
return Enum.GetValues(v.GetType()).Cast<T>().Concat(new[] { default(T) }).Reverse().SkipWhile(e => !v.Equals(e)).Skip(1).First();
}
}
use:
using System;
using System.Linq;
public enum Test { F1, F2, F3 }
public class Program
{
public static void Main()
{
Test t = Test.F3;
Console.WriteLine(t);
Console.WriteLine(t.Next());
Console.WriteLine(t.Previous());
Console.WriteLine("\n");
t = Test.F1;
Console.WriteLine(t);
Console.WriteLine(t.Next());
Console.WriteLine(t.Previous());
}
}
result:
F3
F1
F2
F1
F2
F3
Are you locked into using an enum by something that you have no control over?
If you're not, I'd suggest using an alternative, probably Dictionary<string, int> rat;
If you create a Dictionary and you populate it with your data, enumerating over it is somewhat simpler. Also, it's a clearer mapping of intent-- you're mapping numbers to strings with this enum and you're trying to leverage that mapping.
If you must use the enum, I'd suggest something else:
var rats = new List<eRat>() {eRat.A, eRat.B, eRat.C, eRat.D};
As long as you're adding the values in-order and you keep it in sync, you greatly simplify the act of retrieving the next eRat.
For simple solution, you might just extract array from enum.
eRat[] list = (eRat[])Enum.GetValues(typeof(eRat));
Then you can enumerate
foreach (eRat item in list)
//Do something
Or find next item
int index = Array.IndexOf<eRat>(list, eRat.B);
eRat nextItem = list[index + 1];
Storing the array is better than extracting from enum each time you want next value.
But if you want more beautiful solution, create the class.
public class EnumEnumerator<T> : IEnumerator<T>, IEnumerable<T> {
int _index;
T[] _list;
public EnumEnumerator() {
if (!typeof(T).IsEnum)
throw new NotSupportedException();
_list = (T[])Enum.GetValues(typeof(T));
}
public T Current {
get { return _list[_index]; }
}
public bool MoveNext() {
if (_index + 1 >= _list.Length)
return false;
_index++;
return true;
}
public bool MovePrevious() {
if (_index <= 0)
return false;
_index--;
return true;
}
public bool Seek(T item) {
int i = Array.IndexOf<T>(_list, item);
if (i >= 0) {
_index = i;
return true;
} else
return false;
}
public void Reset() {
_index = 0;
}
public IEnumerator<T> GetEnumerator() {
return ((IEnumerable<T>)_list).GetEnumerator();
}
void IDisposable.Dispose() { }
object System.Collections.IEnumerator.Current {
get { return Current; }
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return _list.GetEnumerator();
}
}
Instantiate
var eRatEnum = new EnumEnumerator<eRat>();
Iterate
foreach (eRat item in eRatEnum)
//Do something
MoveNext
eRatEnum.Seek(eRat.B);
eRatEnum.MoveNext();
eRat nextItem = eRatEnum.Current;
Judging from your description, you don't really want an enum. You're stretching enum beyond its capabilities. Why not create a custom class that exposes the values you need as properties, while keeping them in OrderedDictionary.
Then getting a next/previous one would be trivial.
--update
If you want to enumerate differently on the collection based in the context, make that explicit part of your design.
Encapsulate the items within a class, and have few methods each returning IEnumerable where, T is your desired type.
For example
IEnumerable<Foo> GetFoosByBar()
IEnumerable<Foo> GetFoosByBaz()
etc...
You could simplify it and generalize it some:
static Enum GetNextValue(Enum e){
Array all = Enum.GetValues(e.GetType());
int i = Array.IndexOf(all, e);
if(i < 0)
throw new InvalidEnumArgumentException();
if(i == all.Length - 1)
throw new ArgumentException("No more values", "e");
return (Enum)all.GetValue(i + 1);
}
EDIT:
Note that if your enum contains duplicate values (synonymous entries), then this (or any other technique listed here) will fail, given one of those values. For instance:
enum BRUSHSTYLE{
SOLID = 0,
HOLLOW = 1,
NULL = 1,
HATCHED = 2,
PATTERN = 3,
DIBPATTERN = 5,
DIBPATTERNPT = 6,
PATTERN8X8 = 7,
DIBPATTERN8X8 = 8
}
Given either BRUSHSTYLE.NULL or BRUSHSTYLE.HOLLOW, the return value would be BRUSHSTYLE.HOLLOW.
<leppie>
Update: a generics version:
static T GetNextValue<T>(T e)
{
T[] all = (T[]) Enum.GetValues(typeof(T));
int i = Array.IndexOf(all, e);
if (i < 0)
throw new InvalidEnumArgumentException();
if (i == all.Length - 1)
throw new ArgumentException("No more values", "e");
return all[i + 1];
}
</leppie>
#leppie:
Your generic version allows one to accidentally pass a non-enum value, which will be caught only at run-time. I had originally written it as a generic, but when the compiler rejected where T : Enum, I took it out and realized that I wasn't gaining much from generics anyway. The only real drawback is that you have to cast the result back to your specific enum type.
Hope this part of my code helps you:
public enum EGroupedBy
{
Type,
InterfaceAndType,
Alpha,
_max
}
private void _btnViewUnit_Click(object sender, EventArgs e)
{
int i = (int)GroupedBy;
i = (i + 1) % (int)EGroupedBy._max;
GroupedBy = (EGroupedBy) i;
RefreshUnit();
}
Old post, but I have an alternative solution
//Next with looping
public static Enum Next(this Enum input)
{
Array Arr = Enum.GetValues(input.GetType());
int j = Array.IndexOf(Arr, input) + 1;
return (Arr.Length == j) ? (Enum)Arr.GetValue(0) : (Enum)Arr.GetValue(j);
}
//Previous with looping
public static Enum Prev(this Enum input)
{
Array Arr = Enum.GetValues(input.GetType());
int j = Array.IndexOf(Arr, input) - 1;
return (j == -1) ? (Enum)Arr.GetValue(Arr.Length -1) : (Enum)Arr.GetValue(j);
}
And when you need to use it, just do a cast
BootstrapThemeEnum theme = BootstrapThemeEnum.Info;
var next = (BootstrapThemeEnum)theme.Next();
my enum
public enum BootstrapThemeEnum
{
[Description("white")]
White = 0,
[Description("default")]
Default = 1,
[Description("info")]
Info = 2,
[Description("primary")]
Primary = 3,
[Description("success")]
Success = 4,
[Description("warning")]
Warning = 5,
[Description("danger")]
Danger = 6,
[Description("inverse")]
Inverse = 7
}
I can think of 2 things:
eRat.B+3
Enum.Parse(typeof(((int)eRat.B)+3)
var next = (eRat)((int)someRat + 3);
Seems like an abuse of the enum class to me - but this would do it (assuming that calling Next on the last value would cause wrap-around):
public static eRat Next(this eRat target)
{
var nextValueQuery = Enum.GetValues(typeof(eRat)).Cast<eRat>().SkipWhile(e => e != target).Skip(1);
if (nextValueQuery.Count() != 0)
{
return (eRat)nextValueQuery.First();
}
else
{
return eRat.A;
}
}
And this would give you the previous value on the same basis:
public static eRat Previous(this eRat target)
{
var nextValueQuery = Enum.GetValues(typeof(eRat)).Cast<eRat>().Reverse().SkipWhile(e => e != target).Skip(1);
if (nextValueQuery.Count() != 0)
{
return (eRat)nextValueQuery.First();
}
else
{
return eRat.D;
}
}
I'm using this, perfect for my.
//===================================================================================
// NEXT VALUE IN ENUM
// ex: E_CamModes eNew = kGlobalsVars.eGetNextValue< E_CamModes >( geCmMode );
public static T eGetNextValue< T >( T eIn ){
T[] aiAllValues = ( T[] ) Enum.GetValues( typeof( T ));
int iVal = System.Array.IndexOf( aiAllValues, eIn );
return aiAllValues[ ( iVal + 1 ) % aiAllValues.Length ];
}
There is a very simple solution (if you can change your integer values) that is specifically designed to work with numbers. The fact that your number is an enum, isn't a problem. It is still the integer (or whatever underlying number type you assign). Enum just adds the complexity of a cast requirement.
Assume your enum is defined like this:
public enum ItemStatus
{
New = 0,
Draft = 1,
Received = 2,
Review = 4,
Rejected = 8,
Approved = 16
}
ItemStatus myStatus = ItemStatus.Draft;
Use bitwise operations on the Enum. For Example:
myStatus = (ItemStatus)(((int)myStatus) << 1)
The result is of myStatus is: ItemStatus.Received.
You can also go backwards down the Enum by changing the bitwise operator from << to >>.
myStatus = (ItemStatus)(((int)myStatus) >> 1)
The result is of myStatus is: ItemStatus.New.
You should always add code to test for an "out of bounds" situation in both directions.
You can understand more about bitwise operations here: http://code.tutsplus.com/articles/understanding-bitwise-operators--active-11301
I would go with Sung Meister's answer but here is an alternative:
MyEnum initial = MyEnum.B, next;
for (int i = ((int) initial) + 1, i < int.MaxValue; i++)
{
if (Enum.IsDefined(typeof(MyEnum), (MyEnum) i))
{
next = (MyEnum) i;
break;
}
}
Note: many assumptions assumed :)
From comments I had many question like: "Why would you ever want to use enum in this way." Since so many of you asked, let me give you my use case and see if you agree then:
I have a fixed array of items int[n]. Depending on the situation I want to enumerate through this array differently. So i defined:
int[] Arr= {1,2,34,5,6,78,9,90,30};
enum eRat1 { A = 0, B=3, C=5, D=8 };
enum eRat2 { A, AA,AAA,B,BB,C,C,CC,D };
void walk(Type enumType)
{
foreach (Type t in Enum.GetValues(enumType))
{
write(t.ToString() + " = " + Arr[(int)t)];
}
}
and call walk(typeof(eRAt1)) or walk(typeof(eRAt2))
then i get required output
1) walk(typeof(eRAt1))
A = 1
B = 5
C = 78
D = 30
2) walk(typeof(eRAt2))
A = 1
AA = 2
AAA = 34
B = 5
BB = 6
C = 78
CC = 90
D = 30
This is very simplified. But i hope, this explains. There are some other advantages to this, as having enum.toString(). So basically i use enums as indexers.
So using the solution I can do something like this now.
In sequence eRat1 next value to B is C, but in eRat2 it is BB.
So depending on which sequence I am interested in, I can do e.next and depending on enumType I will either get C or BB. How would one achieve that with dictionaries?
I think this a rather elegant use of enums.
I'm using this here:
public MyEnum getNext() {
return this.ordinal() < MyEnum.values().length - 1 ?
MyEnum.values()[this.ordinal() + 1] :
MyEnum.values()[0];
}
LINQ solution that does not break on last element but continues at the default again:
var nextValue = Enum.GetValues(typeof(EnumT)).Cast<EnumT>().Concat(new[]{default(EnumT)}).SkipWhile(_ => _ != value).Skip(1).First();
I tried the first solution but it did not work for me. Below is my solution:
public object NextEnumItem(object currentEnumItem)
{
if (!currentEnumItem.GetType().IsEnum) throw new
ArgumentException(String.Format("Argument is not an Enum"));
Array Arr = Enum.GetValues(currentEnumItem.GetType());
int j = Array.IndexOf(Arr,currentEnumItem) + 1;
return (Arr.Length == j) ? currentEnumItem : Arr.GetValue(j);
}
public object PreviousEnumItem(object currentEnumItem)
{
if (!currentEnumItem.GetType().IsEnum)
throw new ArgumentException(String.Format("Argument is not an Enum"));
Array Arr = Enum.GetValues(currentEnumItem.GetType());
int j = Array.IndexOf(Arr, currentEnumItem) - 1;
return (j==-1) ? currentEnumItem : Arr.GetValue(j);
}
I did something similar with a different enum. It's for a game and the player has the chance to toggle colors.
public enum PlayerColor {
Red = 0, Green, Blue, Cyan, Yellow, Orange, Purple, Magenta
}
public PlayerColor GetNextFreeColor(PlayerColor oldColor) {
PlayerColor newColor = (PlayerColor)((int)(oldColor + 1) % 8);
return newColor;
}
This solution worked for me.
Based on best answer from Yahya Hussein here is edit of his code for Previous element in Enum
public static class Extensions
{
public static T Previous<T>(this T src) where T : struct
{
if (!typeof(T).IsEnum) throw new ArgumentException(String.Format("Argument {0} is not an Enum", typeof(T).FullName));
T[] Arr = (T[])Enum.GetValues(src.GetType());
int j = Array.IndexOf<T>(Arr, src) - 1;
return (j < 0) ? Arr[Array.Length - 1] : Arr[j];
}
}
enum Level
{
Easy,
Medium,
Expert
};
public static void Main()
{
var difficulty = Level.Easy;
var level = (int)difficulty;
Console.WriteLine(difficulty);
Console.WriteLine(level);
Console.WriteLine("promote level");
level++;
Console.WriteLine(level);
difficulty = (Level)level;
Console.WriteLine(difficulty);
}
You can add and remove integers to an enum to obtain the next value. The only problem is that integer operations on the enum will not check the validity of the enum itself, thus could set "invalid" values.
But you can combine the ++enum and the Enum.IsDefined() to obtain a simple way to get next and previous values of your enum. This would be inefficient in your case since the integer values are not continuous, but if you have continuous integers then it works nicely, and one can check when the ++enum is out of range. Check the next example.
public enum level
{
a = 0,
b = 1,
c = 2,
d = 3,
e = 4
}
private static void Main(string[] args)
{
var levelValue = level.a;
Console.WriteLine(levelValue);
++levelValue;
Console.WriteLine(levelValue);
++levelValue;
Console.WriteLine(levelValue);
++levelValue;
Console.WriteLine(levelValue);
++levelValue;
Console.WriteLine(levelValue);
++levelValue;
Console.WriteLine(Enum.IsDefined(typeof(Program.level), levelValue));
Console.WriteLine(levelValue);
--levelValue;
Console.WriteLine(levelValue);
--levelValue;
Console.WriteLine(levelValue);
--levelValue;
Console.WriteLine(levelValue);
--levelValue;
Console.WriteLine(levelValue);
--levelValue;
Console.WriteLine(Enum.IsDefined(typeof(Program.level), levelValue));
Console.WriteLine(levelValue);
--levelValue;
Console.WriteLine(Enum.IsDefined(typeof(Program.level), levelValue));
Console.WriteLine(levelValue);
}
The output for this would be:
a
b
c
d
e
False
5
e
d
c
b
True
a
False
-1

Categories