Serialize C# Enum Definition to Json - c#

Given the following in C#:
[Flags]
public enum MyFlags {
None = 0,
First = 1 << 0,
Second = 1 << 1,
Third = 1 << 2,
Fourth = 1 << 3
}
Are there any existing methods in ServiceStack.Text for serializing to the following JSON?
{
"MyFlags": {
"None": 0,
"First": 1,
"Second": 2,
"Third": 4,
"Fourth": 8
}
}
Currently I'm using the routine below, are there better ways to do this?
public static string ToJson(this Type type)
{
var stringBuilder = new StringBuilder();
Array values = Enum.GetValues(type);
stringBuilder.Append(string.Format(#"{{ ""{0}"": {{", type.Name));
foreach (Enum value in values)
{
stringBuilder.Append(
string.Format(
#"""{0}"": {1},",
Enum.GetName(typeof(Highlights), value),
Convert.ChangeType(value, value.GetTypeCode())));
}
stringBuilder.Remove(stringBuilder.Length - 1, 1);
stringBuilder.Append("}}");
return stringBuilder.ToString();
}

public static class EnumExtensions
{
public static string EnumToJson(this Type type)
{
if (!type.IsEnum)
throw new InvalidOperationException("enum expected");
var results =
Enum.GetValues(type).Cast<object>()
.ToDictionary(enumValue => enumValue.ToString(), enumValue => (int) enumValue);
return string.Format("{{ \"{0}\" : {1} }}", type.Name, Newtonsoft.Json.JsonConvert.SerializeObject(results));
}
}
Using a dictionary of to do the heavy lifting. Then using Newtonsoft's json convert to convert that to json. I just had to do a bit of wrapping to add the type name on.

You're better off populating a Dictionary<string,int> or a Typed DTO and serializing that.

Related

How to call MemoryMarshal.CreateSpan using Reflection API?

Let's suppose I have this C# structure:
public struct Test
{
public int Code1;
public int Code2;
}
This code works fine:
var test = new Test { Code1 = 1, Code2 = 2 };
var bytes = MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref test, 1));
In bytes, I will get an array of 8 bytes (1, 0, 0, 0, 2, 0, 0, 0).
Now, how can I call the same methods CreateSpan + AsBytes using Reflection API instead of a predefined/generic type?
I have tried this for the CreateSpan part:
private static object GetBytes(object value)
{
var method = typeof(MemoryMarshal).GetMethod(nameof(MemoryMarshal.CreateSpan));
var gmethod = method.MakeGenericMethod(value.GetType());
var parameters = new object[] { value, 1 };
return gmethod.Invoke(null, parameters);
}
But on Invoke (using the same test instance), it says: System.NotSupportedException: 'Specified method is not supported.'
PS: I would like to avoid pointers and unsafe keyword.
You cannot access Span<T> using reflection because it cannot be boxed (to prevent stack references escaping).
The only thing you can do is create a generic function that does all you want it to do, then call that using reflection.
For example, you could return a byte[] array out of a generic function
private static byte[] GetBytes(object value)
{
var method = typeof(ThisType).GetMethod("GetByteArray", BindingFlags.Static | BindingFlags.NonPublic);
var gmethod = method.MakeGenericMethod(value.GetType());
return (byte[])gmethod.Invoke(null, new object[] { value });
}
private static byte[] GetByteArray<T>(T value) where T : struct
{
return MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan<T>(ref value, 1)).ToArray();
}
dotnetfiddle

C# using [Flags] with [Description]

I'm looking to combine the use of enumerations - with the bitwise [Flags] - as well as using a description of the combination of the results. I've looked into examples here using the Flags Attribute, and using the Description Attribute, but not both.
Something like:
[Flags]
public enum ReasonCode
{
[Description("Verified")]
None = 0,
[Description("Check A")]
Reason1 = 1,
[Description("Check B")]
Reason2 = 2,
[Description("Check C")]
Reason3 = 4,
[Description("Check D")]
Reason4 = 8,
[Description("Check E")]
Reason5 = 16,
[Description("Check F")]
Reason6 = 32,
[Description("Check G")]
Reason7 = 64
}
I need to specify all reasons why there was a failure. Using "Reason1", etc... isn't descriptive enough for what I am looking for. I would need a much more verbose description, like "Reason1 - Check A".
For Example:
A value of 5 would be Reason1 and Reason3.
The description would then be:
Failure:
Reason1 - Check A.
Reason3 - Check C.
Is is possible to do combine descriptions like flags?
Here's a more generic extension method that I have used which will deal with all enum values including flag combinations:
public static string GetDescription(this Enum value)
{
//pull out each value in case of flag enumeration
var values = value.ToString().Split(',').Select(s => s.Trim());
var type = value.GetType();
return string.Join(" | ", values.Select(enumValue => type.GetMember(enumValue)
.FirstOrDefault()
?.GetCustomAttribute<DescriptionAttribute>()
?.Description
?? enumValue.ToString()));
}
If a description attribute is not present then it will simply return the value itself.
In order to produce the result you are looking for, use the following code:
public static String GetDescription(ReasonCode reasonCode)
{
if (reasonCode == ReasonCode.None)
return "Verified";
StringBuilder sb = new StringBuilder();
sb.AppendLine("Failed:");
foreach (ReasonCode rc in Enum.GetValues(typeof(ReasonCode)).Cast<ReasonCode>())
{
if (rc == ReasonCode.None)
continue;
if (reasonCode.HasFlag(rc))
sb.AppendLine(rc.ToString() + " - " + GetEnumDescription(rc));
}
return sb.ToString();
}
The code used to retrieve the description value is based on this implementation:
public static String GetEnumDescription(Enum value)
{
String valueText = value.ToString();
Type type = value.GetType();
FieldInfo fi = type.GetField(valueText);
Object[] attributes = fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Length > 0)
{
DescriptionAttribute attribute = (DescriptionAttribute)attributes[0];
return attribute.Description;
}
return valueText;
}
You can find a working demo here.

Converting from object[] always returns Type, not value

I need my Criterion class to accept a variety of types in its constructor, and preserve both the original Type and the value of each. The number of parameters in this term can range from 0 to whatever.
/* Examples of calls:
var c = new Criterion("IsActive", OperationCode.EQUALS, false);
var c = new Criterion("AgeRange", OperationCode.BETWEEN, 18, 35);
*/
public Criterion(string fieldName, OperationCode op, params object[] value) {
string FieldName = fieldName;
OperationCode Op = op;
object[] Value = value;
string display = String.Format("{0} {1} {2}", FieldName, Op, Value[0]);
}
In every case, elements of Value return System.String[], not their value. For the first example call, display will be set to IsActive EQUALS System.String[]. Convert.ToString(Value[0]) does not help, nor does .ToString(). Ideas?
EDIT #1: Dmitry S suggested a test which opened an avenue of exploration. I am calling Criterion with "false" as the only value[] argument. In the Immediate Window, printing value.GetType() reveals that it is, as expected, an Object[].
value[0].GetType() reveals it to be a String[]. While it is originally a string, I have no ideal why .IsArray is true in this case.
When I call it with the integer 14, value[0].GetType() reveals a non-array Int32.
So far, the typing makes sense. But I am interested in retrieving the value, not the type.
try this:
string display = String.Format("{0} {1} {{{2}}}", FieldName, Op, string.Join(", ", value));
if your array looks like
int[]{1, 2, 3, 4}
it will show:
"field Equals {1, 2, 3, 4}"
EDIT
if your values can be also arrays, you may want to use a recursive method:
private string GetValueAsString(object obj)
{
if(obj == null)
return "(null)";
if(obj is IEnumerable)
{
var values = ((IEnumerable)obj).Cast<object>();
return "{" + string.Join(", ", values.Select(GetValueAsString)) + "}";
}
return obj.ToString();
}
This will return
"2" for 2
"Donut" for "Donut"
"{1, 2, 3}" for an array with the values 1, 2 and 3
"{{"Donut", "Pie"}}" for an array that has an string array in the first element, with values "Donut" and "Pie"
"(null)" if the value is null
Hope it helps.
While I don't have your full source, the following imported into a blank project worked as described with minor changes, even on strings and arrays of strings, without mixing the two up:
class Program
{
// not sure which other operations, so I just included these two
public enum OperationCode { EQUALS, BETWEEN }
// made class since it was used that way in your examples
public class Criterion
{
// these have to be declared in the class, instead of the constructor to persist
public string FieldName;
public OperationCode Op;
public object[] Value;
// made this a property so that it will change automatically with FieldName, Op, and Value
public string display { get { return String.Format("{0} {1} {2}", FieldName, Op, Value[0]); } }
// constructor
public Criterion(string fieldName, OperationCode op, params object[] value)
{
FieldName = fieldName;
Op = op;
Value = value;
}
}
// main program tests with different values
static void Main(string[] args)
{
Criterion c;
c = new Criterion("IsActive", OperationCode.EQUALS, false);
Console.WriteLine(c.display);
Console.WriteLine(c.Value[0].GetType().ToString());
Console.WriteLine();
c = new Criterion("AgeRange", OperationCode.BETWEEN, 18, 35);
Console.WriteLine(c.display);
Console.WriteLine(c.Value[0].GetType().ToString());
Console.WriteLine();
c = new Criterion("TitleString", OperationCode.EQUALS, "This is the title.");
Console.WriteLine(c.display);
Console.WriteLine(c.Value[0].GetType().ToString());
Console.WriteLine();
Console.ReadLine();
}
}
Which outputs:
IsActive EQUALS False
System.Boolean
AgeRange BETWEEN 18
System.Int32
TitleString EQUALS This is the title.
System.String
If you want display to show the whole array, then use "[" + String.Join(", ", Value) + "]" or similar instead of Value[0] inside the get block of Criterion.display, as per ivowiblo's answer.
Compiled and ran the following modified code on VisualStudio 2010:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication1
{
public class Criterion
{
public static void Main()
{
// your code goes here
var c = new Criterion("IsActive", OperationCode.EQUALS, false);
c = new Criterion("AgeRange", OperationCode.BETWEEN, 18, 35);
Console.ReadKey();
}
public Criterion(string fieldName, OperationCode op, params object[] value)
{
string FieldName = fieldName;
OperationCode Op = op;
object[] values = value;
object val = values[0];
string display = String.Format("{0} {1} {2}", FieldName, Op, values[0]);
Console.WriteLine(display);
Console.WriteLine(values[0].GetType().Name);
Console.WriteLine(values.GetType().Name);
Console.WriteLine(val.GetType().Name, val);
}
}
public enum OperationCode
{
EQUALS,
BETWEEN
};
}
Output as expected:
IsActive EQUALS False
Boolean
Object[]
Boolean
AgeRange BETWEEN 18
Int32
Object[]
Int32

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

C# Iterating through an enum? (Indexing a System.Array)

I have the following code:
// Obtain the string names of all the elements within myEnum
String[] names = Enum.GetNames( typeof( myEnum ) );
// Obtain the values of all the elements within myEnum
Array values = Enum.GetValues( typeof( myEnum ) );
// Print the names and values to file
for ( int i = 0; i < names.Length; i++ )
{
print( names[i], values[i] );
}
However, I cannot index values. Is there an easier way to do this?
Or have I missed something entirely!
Array values = Enum.GetValues(typeof(myEnum));
foreach( MyEnum val in values )
{
Console.WriteLine (String.Format("{0}: {1}", Enum.GetName(typeof(MyEnum), val), val));
}
Or, you can cast the System.Array that is returned:
string[] names = Enum.GetNames(typeof(MyEnum));
MyEnum[] values = (MyEnum[])Enum.GetValues(typeof(MyEnum));
for( int i = 0; i < names.Length; i++ )
{
print(names[i], values[i]);
}
But, can you be sure that GetValues returns the values in the same order as GetNames returns the names ?
You need to cast the array - the returned array is actually of the requested type, i.e. myEnum[] if you ask for typeof(myEnum):
myEnum[] values = (myEnum[]) Enum.GetValues(typeof(myEnum));
Then values[0] etc
You can cast that Array to different types of Arrays:
myEnum[] values = (myEnum[])Enum.GetValues(typeof(myEnum));
or if you want the integer values:
int[] values = (int[])Enum.GetValues(typeof(myEnum));
You can iterate those casted arrays of course :)
How about a dictionary list?
Dictionary<string, int> list = new Dictionary<string, int>();
foreach( var item in Enum.GetNames(typeof(MyEnum)) )
{
list.Add(item, (int)Enum.Parse(typeof(MyEnum), item));
}
and of course you can change the dictionary value type to whatever your enum values are.
What about using a foreach loop, maybe you could work with that?
int i = 0;
foreach (var o in values)
{
print(names[i], o);
i++;
}
something like that perhaps?
Here is another. We had a need to provide friendly names for our EnumValues. We used the System.ComponentModel.DescriptionAttribute to show a custom string value for each enum value.
public static class StaticClass
{
public static string GetEnumDescription(Enum currentEnum)
{
string description = String.Empty;
DescriptionAttribute da;
FieldInfo fi = currentEnum.GetType().
GetField(currentEnum.ToString());
da = (DescriptionAttribute)Attribute.GetCustomAttribute(fi,
typeof(DescriptionAttribute));
if (da != null)
description = da.Description;
else
description = currentEnum.ToString();
return description;
}
public static List<string> GetEnumFormattedNames<TEnum>()
{
var enumType = typeof(TEnum);
if (enumType == typeof(Enum))
throw new ArgumentException("typeof(TEnum) == System.Enum", "TEnum");
if (!(enumType.IsEnum))
throw new ArgumentException(String.Format("typeof({0}).IsEnum == false", enumType), "TEnum");
List<string> formattedNames = new List<string>();
var list = Enum.GetValues(enumType).OfType<TEnum>().ToList<TEnum>();
foreach (TEnum item in list)
{
formattedNames.Add(GetEnumDescription(item as Enum));
}
return formattedNames;
}
}
In Use
public enum TestEnum
{
[Description("Something 1")]
Dr = 0,
[Description("Something 2")]
Mr = 1
}
static void Main(string[] args)
{
var vals = StaticClass.GetEnumFormattedNames<TestEnum>();
}
This will end returning "Something 1", "Something 2"
Another solution, with interesting possibilities:
enum Days { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }
static class Helpers
{
public static IEnumerable<Days> AllDays(Days First)
{
if (First == Days.Monday)
{
yield return Days.Monday;
yield return Days.Tuesday;
yield return Days.Wednesday;
yield return Days.Thursday;
yield return Days.Friday;
yield return Days.Saturday;
yield return Days.Sunday;
}
if (First == Days.Saturday)
{
yield return Days.Saturday;
yield return Days.Sunday;
yield return Days.Monday;
yield return Days.Tuesday;
yield return Days.Wednesday;
yield return Days.Thursday;
yield return Days.Friday;
}
}
Old question, but a slightly cleaner approach using LINQ's .Cast<>()
var values = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>();
foreach(var val in values)
{
Console.WriteLine("Member: {0}",val.ToString());
}
In the Enum.GetValues results, casting to int produces the numeric value. Using ToString() produces the friendly name. No other calls to Enum.GetName are needed.
public enum MyEnum
{
FirstWord,
SecondWord,
Another = 5
};
// later in some method
StringBuilder sb = new StringBuilder();
foreach (var val in Enum.GetValues(typeof(MyEnum))) {
int numberValue = (int)val;
string friendyName = val.ToString();
sb.Append("Enum number " + numberValue + " has the name " + friendyName + "\n");
}
File.WriteAllText(#"C:\temp\myfile.txt", sb.ToString());
// Produces the output file contents:
/*
Enum number 0 has the name FirstWord
Enum number 1 has the name SecondWord
Enum number 5 has the name Another
*/
Array has a GetValue(Int32) method which you can use to retrieve the value at a specified index.
Array.GetValue
You can simplify this using format strings. I use the following snippet in usage messages:
writer.WriteLine("Exit codes are a combination of the following:");
foreach (ExitCodes value in Enum.GetValues(typeof(ExitCodes)))
{
writer.WriteLine(" {0,4:D}: {0:G}", value);
}
The D format specifier formats the enum value as a decimal. There's also an X specifier that gives hexadecimal output.
The G specifier formats an enum as a string. If the Flags attribute is applied to the enum then combined values are supported as well. There's an F specifier that acts as if Flags is always present.
See Enum.Format().
Here is a simple way to iterate through your custom Enum object
For Each enumValue As Integer In [Enum].GetValues(GetType(MyEnum))
Print([Enum].GetName(GetType(MyEnum), enumValue).ToString)
Next
Ancient question, but 3Dave's answer supplied the easiest approach. I needed a little helper method to generate a Sql script to decode an enum value in the database for debugging. It worked great:
public static string EnumToCheater<T>() {
var sql = "";
foreach (var enumValue in Enum.GetValues(typeof(T)))
sql += $#"when {(int) enumValue} then '{enumValue}' ";
return $#"case ?? {sql}else '??' end,";
}
I have it in a static method, so usage is:
var cheater = MyStaticClass.EnumToCheater<MyEnum>()

Categories