C# Implicit Conversion from Enum to different Enum [duplicate] - c#

Is it possible to define an implicit conversion of enums in c#?
something that could achieve this?
public enum MyEnum
{
one = 1, two = 2
}
MyEnum number = MyEnum.one;
long i = number;
If not, why not?

There is a solution. Consider the following:
public sealed class AccountStatus
{
public static readonly AccountStatus Open = new AccountStatus(1);
public static readonly AccountStatus Closed = new AccountStatus(2);
public static readonly SortedList<byte, AccountStatus> Values = new SortedList<byte, AccountStatus>();
private readonly byte Value;
private AccountStatus(byte value)
{
this.Value = value;
Values.Add(value, this);
}
public static implicit operator AccountStatus(byte value)
{
return Values[value];
}
public static implicit operator byte(AccountStatus value)
{
return value.Value;
}
}
The above offers implicit conversion:
AccountStatus openedAccount = 1; // Works
byte openedValue = AccountStatus.Open; // Works
This is a fair bit more work than declaring a normal enum (though you can refactor some of the above into a common generic base class). You can go even further by having the base class implement IComparable & IEquatable, as well as adding methods to return the value of DescriptionAttributes, declared names, etc, etc.
I wrote a base class (RichEnum<>) to handle most fo the grunt work, which eases the above declaration of enums down to:
public sealed class AccountStatus : RichEnum<byte, AccountStatus>
{
public static readonly AccountStatus Open = new AccountStatus(1);
public static readonly AccountStatus Closed = new AccountStatus(2);
private AccountStatus(byte value) : base (value)
{
}
public static implicit operator AccountStatus(byte value)
{
return Convert(value);
}
}
The base class (RichEnum) is listed below.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Resources;
namespace Ethica
{
using Reflection;
using Text;
[DebuggerDisplay("{Value} ({Name})")]
public abstract class RichEnum<TValue, TDerived>
: IEquatable<TDerived>,
IComparable<TDerived>,
IComparable, IComparer<TDerived>
where TValue : struct , IComparable<TValue>, IEquatable<TValue>
where TDerived : RichEnum<TValue, TDerived>
{
#region Backing Fields
/// <summary>
/// The value of the enum item
/// </summary>
public readonly TValue Value;
/// <summary>
/// The public field name, determined from reflection
/// </summary>
private string _name;
/// <summary>
/// The DescriptionAttribute, if any, linked to the declaring field
/// </summary>
private DescriptionAttribute _descriptionAttribute;
/// <summary>
/// Reverse lookup to convert values back to local instances
/// </summary>
private static SortedList<TValue, TDerived> _values;
private static bool _isInitialized;
#endregion
#region Constructors
protected RichEnum(TValue value)
{
if (_values == null)
_values = new SortedList<TValue, TDerived>();
this.Value = value;
_values.Add(value, (TDerived)this);
}
#endregion
#region Properties
public string Name
{
get
{
CheckInitialized();
return _name;
}
}
public string Description
{
get
{
CheckInitialized();
if (_descriptionAttribute != null)
return _descriptionAttribute.Description;
return _name;
}
}
#endregion
#region Initialization
private static void CheckInitialized()
{
if (!_isInitialized)
{
ResourceManager _resources = new ResourceManager(typeof(TDerived).Name, typeof(TDerived).Assembly);
var fields = typeof(TDerived)
.GetFields(BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public)
.Where(t => t.FieldType == typeof(TDerived));
foreach (var field in fields)
{
TDerived instance = (TDerived)field.GetValue(null);
instance._name = field.Name;
instance._descriptionAttribute = field.GetAttribute<DescriptionAttribute>();
var displayName = field.Name.ToPhrase();
}
_isInitialized = true;
}
}
#endregion
#region Conversion and Equality
public static TDerived Convert(TValue value)
{
return _values[value];
}
public static bool TryConvert(TValue value, out TDerived result)
{
return _values.TryGetValue(value, out result);
}
public static implicit operator TValue(RichEnum<TValue, TDerived> value)
{
return value.Value;
}
public static implicit operator RichEnum<TValue, TDerived>(TValue value)
{
return _values[value];
}
public static implicit operator TDerived(RichEnum<TValue, TDerived> value)
{
return value;
}
public override string ToString()
{
return _name;
}
#endregion
#region IEquatable<TDerived> Members
public override bool Equals(object obj)
{
if (obj != null)
{
if (obj is TValue)
return Value.Equals((TValue)obj);
if (obj is TDerived)
return Value.Equals(((TDerived)obj).Value);
}
return false;
}
bool IEquatable<TDerived>.Equals(TDerived other)
{
return Value.Equals(other.Value);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
#endregion
#region IComparable Members
int IComparable<TDerived>.CompareTo(TDerived other)
{
return Value.CompareTo(other.Value);
}
int IComparable.CompareTo(object obj)
{
if (obj != null)
{
if (obj is TValue)
return Value.CompareTo((TValue)obj);
if (obj is TDerived)
return Value.CompareTo(((TDerived)obj).Value);
}
return -1;
}
int IComparer<TDerived>.Compare(TDerived x, TDerived y)
{
return (x == null) ? -1 :
(y == null) ? 1 :
x.Value.CompareTo(y.Value);
}
#endregion
public static IEnumerable<TDerived> Values
{
get
{
return _values.Values;
}
}
public static TDerived Parse(string name)
{
foreach (TDerived value in _values.Values)
if (0 == string.Compare(value.Name, name, true) || 0 == string.Compare(value.DisplayName, name, true))
return value;
return null;
}
}
}

You can't do implict conversions (except for zero), and you can't write your own instance methods - however, you can probably write your own extension methods:
public enum MyEnum { A, B, C }
public static class MyEnumExt
{
public static int Value(this MyEnum foo) { return (int)foo; }
static void Main()
{
MyEnum val = MyEnum.A;
int i = val.Value();
}
}
This doesn't give you a lot, though (compared to just doing an explicit cast).
One of the main times I've seen people want this is for doing [Flags] manipulation via generics - i.e. a bool IsFlagSet<T>(T value, T flag); method. Unfortunately, C# 3.0 doesn't support operators on generics, but you can get around this using things like this, which make operators fully available with generics.

struct PseudoEnum
{
public const int
INPT = 0,
CTXT = 1,
OUTP = 2;
};
// ...
var arr = new String[3];
arr[PseudoEnum.CTXT] = "can";
arr[PseudoEnum.INPT] = "use";
arr[PseudoEnum.CTXT] = "as";
arr[PseudoEnum.CTXT] = "array";
arr[PseudoEnum.OUTP] = "index";

I adapted Mark's excellent RichEnum generic baseclass.
Fixing
a number of compilation problems due to missing bits from his libraries (notably: the resource dependent display names weren't completely removed; they are now)
initialization wasn't perfect: if the first thing you did was access the static .Values property from the base class, you'd get a NPE. Fixed this by forcing the base class to curiously-recursively (CRTP) force the static construction of TDerived just in time during CheckInitialized
finally moved CheckInitialized logic into a static constructor (to avoid the penalty of checking each time, the race condition on multithreaded initialization; perhaps this was an impossibility solved by my bullet 1.?)
Kudos to Mark for the splendid idea + implementation, here's to you all:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Resources;
namespace NMatrix
{
[DebuggerDisplay("{Value} ({Name})")]
public abstract class RichEnum<TValue, TDerived>
: IEquatable<TDerived>,
IComparable<TDerived>,
IComparable, IComparer<TDerived>
where TValue : struct, IComparable<TValue>, IEquatable<TValue>
where TDerived : RichEnum<TValue, TDerived>
{
#region Backing Fields
/// <summary>
/// The value of the enum item
/// </summary>
public readonly TValue Value;
/// <summary>
/// The public field name, determined from reflection
/// </summary>
private string _name;
/// <summary>
/// The DescriptionAttribute, if any, linked to the declaring field
/// </summary>
private DescriptionAttribute _descriptionAttribute;
/// <summary>
/// Reverse lookup to convert values back to local instances
/// </summary>
private static readonly SortedList<TValue, TDerived> _values = new SortedList<TValue, TDerived>();
#endregion
#region Constructors
protected RichEnum(TValue value)
{
this.Value = value;
_values.Add(value, (TDerived)this);
}
#endregion
#region Properties
public string Name
{
get
{
return _name;
}
}
public string Description
{
get
{
if (_descriptionAttribute != null)
return _descriptionAttribute.Description;
return _name;
}
}
#endregion
#region Initialization
static RichEnum()
{
var fields = typeof(TDerived)
.GetFields(BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public)
.Where(t => t.FieldType == typeof(TDerived));
foreach (var field in fields)
{
/*var dummy =*/ field.GetValue(null); // forces static initializer to run for TDerived
TDerived instance = (TDerived)field.GetValue(null);
instance._name = field.Name;
instance._descriptionAttribute = field.GetCustomAttributes(true).OfType<DescriptionAttribute>().FirstOrDefault();
}
}
#endregion
#region Conversion and Equality
public static TDerived Convert(TValue value)
{
return _values[value];
}
public static bool TryConvert(TValue value, out TDerived result)
{
return _values.TryGetValue(value, out result);
}
public static implicit operator TValue(RichEnum<TValue, TDerived> value)
{
return value.Value;
}
public static implicit operator RichEnum<TValue, TDerived>(TValue value)
{
return _values[value];
}
public static implicit operator TDerived(RichEnum<TValue, TDerived> value)
{
return value;
}
public override string ToString()
{
return _name;
}
#endregion
#region IEquatable<TDerived> Members
public override bool Equals(object obj)
{
if (obj != null)
{
if (obj is TValue)
return Value.Equals((TValue)obj);
if (obj is TDerived)
return Value.Equals(((TDerived)obj).Value);
}
return false;
}
bool IEquatable<TDerived>.Equals(TDerived other)
{
return Value.Equals(other.Value);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
#endregion
#region IComparable Members
int IComparable<TDerived>.CompareTo(TDerived other)
{
return Value.CompareTo(other.Value);
}
int IComparable.CompareTo(object obj)
{
if (obj != null)
{
if (obj is TValue)
return Value.CompareTo((TValue)obj);
if (obj is TDerived)
return Value.CompareTo(((TDerived)obj).Value);
}
return -1;
}
int IComparer<TDerived>.Compare(TDerived x, TDerived y)
{
return (x == null) ? -1 :
(y == null) ? 1 :
x.Value.CompareTo(y.Value);
}
#endregion
public static IEnumerable<TDerived> Values
{
get
{
return _values.Values;
}
}
public static TDerived Parse(string name)
{
foreach (TDerived value in Values)
if (0 == string.Compare(value.Name, name, true))
return value;
return null;
}
}
}
A sample of usage that I ran on mono:
using System.ComponentModel;
using System;
namespace NMatrix
{
public sealed class MyEnum : RichEnum<int, MyEnum>
{
[Description("aap")] public static readonly MyEnum my_aap = new MyEnum(63000);
[Description("noot")] public static readonly MyEnum my_noot = new MyEnum(63001);
[Description("mies")] public static readonly MyEnum my_mies = new MyEnum(63002);
private MyEnum(int value) : base (value) { }
public static implicit operator MyEnum(int value) { return Convert(value); }
}
public static class Program
{
public static void Main(string[] args)
{
foreach (var enumvalue in MyEnum.Values)
Console.WriteLine("MyEnum {0}: {1} ({2})", (int) enumvalue, enumvalue, enumvalue.Description);
}
}
}
Producing the output
[mono] ~/custom/demo # gmcs test.cs richenum.cs && ./test.exe
MyEnum 63000: my_aap (aap)
MyEnum 63001: my_noot (noot)
MyEnum 63002: my_mies (mies)
Note: mono 2.6.7 requires an extra explicit cast that is not required when using mono 2.8.2...

You cannot declare implicit conversions on enum types, because they can't define methods. The C# implicit keyword compiles into a method starting with 'op_', and it wouldn't work in this case.

You probably could, but not for the enum (you can't add a method to it). You could add an implicit conversion to you own class to allow an enum to be converted to it,
public class MyClass {
public static implicit operator MyClass ( MyEnum input ) {
//...
}
}
MyClass m = MyEnum.One;
The question would be why?
In general .Net avoids (and you should too) any implicit conversion where data can be lost.

enums are largely useless for me because of this, OP.
I end up doing pic-related all the time:
the simple solution
classic example problem is the VirtualKey set for detecting keypresses.
enum VKeys : ushort
{
a = 1,
b = 2,
c = 3
}
// the goal is to index the array using predefined constants
int[] array = new int[500];
var x = array[VKeys.VK_LSHIFT];
problem here is you can't index the array with the enum because it can't implicitly convert enum to ushort (even though we even based the enum on ushort)
in this specific context, enums are obsoleted by the following datastructure
. . . .
public static class VKeys
{
public const ushort
a = 1,
b = 2,
c = 3;
}

I found even easier solution taken from here https://codereview.stackexchange.com/questions/7566/enum-vs-int-wrapper-struct I pasted the code below from that link just in case it does not work in the future.
struct Day
{
readonly int day;
public static readonly Day Monday = 0;
public static readonly Day Tuesday = 1;
public static readonly Day Wednesday = 2;
public static readonly Day Thursday = 3;
public static readonly Day Friday = 4;
public static readonly Day Saturday = 5;
public static readonly Day Sunday = 6;
private Day(int day)
{
this.day = day;
}
public static implicit operator int(Day value)
{
return value.day;
}
public static implicit operator Day(int value)
{
return new Day(value);
}
}

I created this utility to help me convert an Enum to PrimitiveEnum and PrimitiveEnum to byte, sbyte, short, ushort, int, uint, long, or ulong.
So, this technically converts any enum to any its primitive value.
public enum MyEnum
{
one = 1, two = 2
}
PrimitiveEnum number = MyEnum.one;
long i = number;
See commit at https://github.com/McKabue/McKabue.Extentions.Utility/blob/master/src/McKabue.Extentions.Utility/Enums/PrimitiveEnum.cs
using System;
namespace McKabue.Extentions.Utility.Enums
{
/// <summary>
/// <see href="https://stackoverflow.com/q/261663/3563013">
/// Can we define implicit conversions of enums in c#?
/// </see>
/// </summary>
public struct PrimitiveEnum
{
private Enum _enum;
public PrimitiveEnum(Enum _enum)
{
this._enum = _enum;
}
public Enum Enum => _enum;
public static implicit operator PrimitiveEnum(Enum _enum)
{
return new PrimitiveEnum(_enum);
}
public static implicit operator Enum(PrimitiveEnum primitiveEnum)
{
return primitiveEnum.Enum;
}
public static implicit operator byte(PrimitiveEnum primitiveEnum)
{
return Convert.ToByte(primitiveEnum.Enum);
}
public static implicit operator sbyte(PrimitiveEnum primitiveEnum)
{
return Convert.ToSByte(primitiveEnum.Enum);
}
public static implicit operator short(PrimitiveEnum primitiveEnum)
{
return Convert.ToInt16(primitiveEnum.Enum);
}
public static implicit operator ushort(PrimitiveEnum primitiveEnum)
{
return Convert.ToUInt16(primitiveEnum.Enum);
}
public static implicit operator int(PrimitiveEnum primitiveEnum)
{
return Convert.ToInt32(primitiveEnum.Enum);
}
public static implicit operator uint(PrimitiveEnum primitiveEnum)
{
return Convert.ToUInt32(primitiveEnum.Enum);
}
public static implicit operator long(PrimitiveEnum primitiveEnum)
{
return Convert.ToInt64(primitiveEnum.Enum);
}
public static implicit operator ulong(PrimitiveEnum primitiveEnum)
{
return Convert.ToUInt64(primitiveEnum.Enum);
}
}
}

If you define the base of the enum as a long then you can perform explicit conversion. I don't know if you can use implicit conversions as enums cannot have methods defined on them.
public enum MyEnum : long
{
one = 1,
two = 2,
}
MyEnum number = MyEnum.one;
long i = (long)number;
Also, be aware with this that an uninitalised enumeration will default to the 0 value, or the first item - so in the situation above it would probably be best to define zero = 0 as well.

I've worked around an issue with sehe's answer when running the code on MS .net (non-Mono). For me specifically the issue occurred on .net 4.5.1 but other versions seem affected, too.
The issue
accessing a public static TDervied MyEnumValue by reflection (via FieldInfo.GetValue(null) does not initialize said field.
The workaround
Instead of assigning names to TDerived instances upon the static initializer of RichEnum<TValue, TDerived> this is done lazily on first access of TDerived.Name. The code:
public abstract class RichEnum<TValue, TDerived> : EquatableBase<TDerived>
where TValue : struct, IComparable<TValue>, IEquatable<TValue>
where TDerived : RichEnum<TValue, TDerived>
{
// Enforcing that the field Name (´SomeEnum.SomeEnumValue´) is the same as its
// instances ´SomeEnum.Name´ is done by the static initializer of this class.
// Explanation of initialization sequence:
// 1. the static initializer of ´RichEnum<TValue, TDerived>´ reflects TDervied and
// creates a list of all ´public static TDervied´ fields:
// ´EnumInstanceToNameMapping´
// 2. the static initializer of ´TDerive´d assigns values to these fields
// 3. The user is now able to access the values of a field.
// Upon first access of ´TDervied.Name´ we search the list
// ´EnumInstanceToNameMapping´ (created at step 1) for the field that holds
// ´this´ instance of ´TDerived´.
// We then get the Name for ´this´ from the FieldInfo
private static readonly IReadOnlyCollection<EnumInstanceReflectionInfo>
EnumInstanceToNameMapping =
typeof(TDerived)
.GetFields(BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public)
.Where(t => t.FieldType == typeof(TDerived))
.Select(fieldInfo => new EnumInstanceReflectionInfo(fieldInfo))
.ToList();
private static readonly SortedList<TValue, TDerived> Values =
new SortedList<TValue, TDerived>();
public readonly TValue Value;
private readonly Lazy<string> _name;
protected RichEnum(TValue value)
{
Value = value;
// SortedList doesn't allow duplicates so we don't need to do
// duplicate checking ourselves
Values.Add(value, (TDerived)this);
_name = new Lazy<string>(
() => EnumInstanceToNameMapping
.First(x => ReferenceEquals(this, x.Instance))
.Name);
}
public string Name
{
get { return _name.Value; }
}
public static implicit operator TValue(RichEnum<TValue, TDerived> richEnum)
{
return richEnum.Value;
}
public static TDerived Convert(TValue value)
{
return Values[value];
}
protected override bool Equals(TDerived other)
{
return Value.Equals(other.Value);
}
protected override int ComputeHashCode()
{
return Value.GetHashCode();
}
private class EnumInstanceReflectionInfo
{
private readonly FieldInfo _field;
private readonly Lazy<TDerived> _instance;
public EnumInstanceReflectionInfo(FieldInfo field)
{
_field = field;
_instance = new Lazy<TDerived>(() => (TDerived)field.GetValue(null));
}
public TDerived Instance
{
get { return _instance.Value; }
}
public string Name { get { return _field.Name; } }
}
}
which - in my case - is based upon EquatableBase<T>:
public abstract class EquatableBase<T>
where T : class
{
public override bool Equals(object obj)
{
if (this == obj)
{
return true;
}
T other = obj as T;
if (other == null)
{
return false;
}
return Equals(other);
}
protected abstract bool Equals(T other);
public override int GetHashCode()
{
unchecked
{
return ComputeHashCode();
}
}
protected abstract int ComputeHashCode();
}
Note
The above code does not incorporate all features of Mark's original answer!
Thanks
Thanks to Mark for providing his RichEnum implementation and thanks to sehe for providing some improvements!

Here's a different flavour based on adminSoftDK's answer.
/// <summary>
/// Based on https://datatracker.ietf.org/doc/html/rfc4346#appendix-A.1
/// </summary>
[DebuggerDisplay("{_value}")]
public struct HandshakeContentType
{
#region Types
public const byte ChangeCipher = 0x14;
public const byte Alert = 0x15;
public const byte Handshake = 0x16;
public const byte ApplicationData = 0x17;
#endregion
byte _value;
private HandshakeContentType(byte value)
{
_value = value;
switch (_value)
{
case ChangeCipher:
case Alert:
case Handshake:
case ApplicationData:
break;
default:
throw new InvalidOperationException($"An invalid handshake content type (${value}) was provided.");
}
}
#region Methods
public static implicit operator byte(HandshakeContentType type) => type._value;
public static implicit operator HandshakeContentType(byte b) => new HandshakeContentType(b);
#endregion
}
This allows you to use this struct with switch statements which I think is pretty awesome.

#BatteryBackupUnit
Hey this sounds like a cool solution but could you explain this part here?
Since im getting with .NET 4.7.2 an "InvalidCastException" out of this sadly :/
_name = new Lazy<string>(
() => EnumInstanceToNameMapping
.First(x => ReferenceEquals(this, x.Instance))
.Name);
I dont know why, i have created a derived type of the RichEnum and initialized as everything u did in the example but i getthis annyoingg exception..
Would be glad of some help to this since i like this approach alot tbh.

I don't have enough rep to add a comment, but I was inspired by the 'struct' comment here:
https://stackoverflow.com/a/39141171/12135042
Here is how I did it:
public enum DaysOfWeek
{
Sunday = 0,
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 7,
}
public struct Weekends
{
private Weekends(DaysOfWeek day){ Day = day; }
public readonly DaysOfWeek Day;
public static Weekends Sunday = new(DaysOfWeek.Sunday);
public static Weekends Saturday = new(DaysOfWeek.Saturday);
public static implicit operator DaysOfWeek(Weekends value) => value.Mode;
}
I feel this gets the best of both worlds here, since you get your super enum, and easily accessible structs that are statically accessibly acting as subsets of the superenum.

Introducing implicit conversions for enum types would break type safety, so I'd not recommend to do that. Why would you want to do that? The only use case for this I've seen is when you want to put the enum values into a structure with a pre-defined layout. But even then, you can use the enum type in the structure and just tell the Marshaller what he should do with this.

Related

Generic class for enumerations - casting issue

I want to write a generic class that accepts enumerations. Since this class is intended to implement some interfaces, the main aim is to be able to treat enumerations as other objects implementing those interfaces(e.g. for list extensions, etc). Hence, for a sample enum
public enum QEnum : int
{
xlNoValue = 0,
xlSomeValue = 1
}
public static class QEnumExtensions
{
public static string toString(this QEnum xThis)
{
...
}
public static QEnum toEnum(this string xThis)
{
...
}
}
I would like to declare a generic class such as
public class QEnumHolder<T> where T : struct, IConvertible
{
private T mxVal = default(T);
public QEnumHolder()
{
if (!typeof(T).IsEnum) throw new NotSupportedException();
}
public QEnumHolder(T xVal)
{
if (!typeof(T).IsEnum) throw new NotSupportedException();
mxVal = xVal;
}
static public implicit operator QEnumHolder<T>(T xVal)
{
return new QEnumHolder<T>(xVal);
}
static public implicit operator T(QEnumHolder<T> xVal)
{
return (T)xVal.mxVal;
}
public string toString()
{
if (mxVal is QEnum) return ((QEnum)Convert.ToInt32(mxVal)).toString();
...
}
public void fromString(string xString)
{
if (mxVal is QEnum)
mxVal = (???)xString.toEnum(); // problem
}
}
All of the enumerations that we use implement
toString() function which returns a "nice" string that can go into comboBoxes, etc
conversion of string to enumeration, as above
hence the structure of toString/toEnum is pretty much given. The problem is with the last code line marked "problem". I have no idea how to tell the compiler that in this branch, the return type of toEnum() and T will be the same.
I tried to circumvent the problem by declaring mxVal as int and using Convert.ToInt32 everywhere. However, then I run into problem in the operator T where the compiler has objections against converting int to a T (the compiler can't know that T will be enum, hence I can't use none of the "int to enum conversion" discussions here on SO).
A better design would be to use some naming convention, put all your enum extension methods in one and the same static class, and bind these functions inside your holder class static constructor. Something like this:
public static partial class MyEnumExtensions
{
public static MyEnumHolder<T> ToHolder<T>(this T source)
where T : struct, IConvertible
{
return new MyEnumHolder<T>(source);
}
}
public class MyEnumHolder<T> where T : struct, IConvertible
{
static readonly Func<T, string> toStringFunc;
static readonly Func<string, T> toEnumFunc;
static MyEnumHolder()
{
if (!typeof(T).IsEnum) throw new NotSupportedException();
// Use your naming conventions
var name = typeof(T).Name;
toStringFunc = (Func<T, string>)Delegate.CreateDelegate(typeof(Func<T, string>),
typeof(MyEnumExtensions).GetMethod("toString", new[] { typeof(T) }));
toEnumFunc = (Func<string, T>)Delegate.CreateDelegate(typeof(Func<string, T>),
typeof(MyEnumExtensions).GetMethod("to" + name, new[] { typeof(string) }));
}
private T value;
public MyEnumHolder() { value = default(T); }
public MyEnumHolder(T value) { this.value = value; }
static public implicit operator MyEnumHolder<T>(T x) { return new MyEnumHolder<T>(x); }
static public implicit operator T(MyEnumHolder<T> x) { return x.value; }
public string toString()
{
return toStringFunc(value);
}
public void fromString(string xString)
{
value = toEnumFunc(xString);
}
}
Sample enum definitions (could be in separate files, but must be inside the same project):
public enum MyEnumA { A1, A2, A3 }
partial class MyEnumExtensions
{
public static string toString(this MyEnumA x)
{
//...
return x.ToString();
}
public static MyEnumA toMyEnumA(this string x)
{
//...
return (MyEnumA)Enum.Parse(typeof(MyEnumA), x);
}
}
and
public enum MyEnumB { B1, B2, B3 }
partial class MyEnumExtensions
{
public static string toString(this MyEnumB x)
{
//...
return x.ToString();
}
public static MyEnumB toMyEnumB(this string x)
{
//...
return (MyEnumB)Enum.Parse(typeof(MyEnumB), x);
}
}
test:
var a = MyEnumA.A1.ToHolder();
var sA = a.toString();
a.fromString("A2");
var b = MyEnumB.B2.ToHolder();
var sB = b.toString();
b.fromString("B1");
mxVal = (T)(object)xString.toEnum();

type casting classes mimiking enums

I use a 3rd party application for output. There are several int properties and I would like to handle the different properties' int values via enum.
Property1 could be 0,1,2
Property2 could be 0,1
Property3 could be 1,2
I think I should have enum inheritance which is not option in c#.
So I solved it by using classes (I'm using Tono Nam's answer from another topic to this end: https://stackoverflow.com/a/23430174/4273304).
public class MyEnum : IEquatable<MyEnum>
{
public static readonly MyEnum Undefined = new MyEnum(-1, "Undefined");
public int Value { get; private set; }
public string Name { get; private set; }
protected MyEnum(int value, string name)
{
this.Value = value;
this.Name = name;
}
public bool Equals(MyEnum b)
{
return this.Name == b.Name && this.Value == b.Value;
}
public override string ToString()
{
return this.Name;
}
public static T Parse<T>(int value)
{
object obj;
Type t_type = typeof(T);
var fiList = t_type.GetFields(BindingFlags.Public | BindingFlags.Static).Where(f => f.FieldType == typeof(T)).ToArray();
foreach(FieldInfo en in fiList)
{
object tmp = en.GetValue(null);
if (((MyEnum)tmp).Value == value)
return (T)tmp;
}
obj = MyEnum.Undefined;
return (T)obj;
}
}
public class MyEnumChild1 : MyEnum
{
public static readonly MyEnumChild1 A = new MyEnumChild1(0, "A");
public static readonly MyEnumChild1 B = new MyEnumChild1(1, "B");
private MyEnumChild1(int value, string name)
: base(value, name)
{
}
}
public class MyEnumChild2 : MyEnum
{
public static readonly MyEnumChild2 A = new MyEnumChild2(0, "A");
public static readonly MyEnumChild2 C = new MyEnumChild2(1, "C");
private MyEnumChild2(int value, string name)
: base(value, name)
{
}
}
public class MyEnumChild3 : MyEnum
{
public static readonly MyEnumChild3 D = new MyEnumChild3(0, "D");
public static readonly MyEnumChild3 E = new MyEnumChild3(1, "E");
private MyEnumChild3(int value, string name)
: base(value, name)
{
}
}
This solution serves my purposes, but I dont know how to cast an int to MyEnumChild1.
I created a parser method:
MyEnumChild1 MEC1 = MyEnum.Parse <MyEnumChild1>(1);
It seems to work fine, MEC1 is MyEnumChild1.B now, but I'm not sure of it.
How safe do you think my parser method is? Are there any mistakes in this code or can I use it safely?
Do you know any better, elegant or simpler solution for the cast?
First, your Parse method should put a constraint on T:
public static T Parse<T>(int value) where T : MyEnum
Second, you can make it protected instead and implement a casting operator in each of the derived enums this way:
public static explicit operator MyEnumChild1(int value)
{
return Parse<MyEnumChild1>(value);
}
And use it in a more classic way:
MyEnumChild1 mec1 = (MyEnumChild1)1

Delegates to generic operations where the generic type is unknown. How to create something like that?

Suppose I have the following code.
static class Store<T> {
public static T A;
public static T B;
public static T C;
}
public static class Store {
public static Value A = new Value(<T>(v) => Store<T>.A = v); //just an example of what I want
public static Value B = new Value(<T>(v) => Store<T>.B = v); //just an example of what I want
public static Value C = new Value(SetC<T>); //just an example of what I want
public static void SetA<T>(T value) { Store<T>.A = value; }
public static void SetB<T>(T value) { Store<T>.B = value; }
public static void SetC<T>(T value) { Store<T>.C = value; }
}
public class Value {
Action<T><T> _valueChanger; //just an example of what I want
public Value(Action<T><T> valueChanger) { //just an example of what I want
_valueChanger = valueChanger;
}
public void SetValue<T> (T value) {
_valueChanger<T>(value); //just an example of what I want
}
}
I want to write Store.A.SetValue(42) so that the value is saved to Store<int>.A. What can I write instead of the lines marked by "just an example of what I want" to make that happen? (I want to explore a solution that doesn't involve dictionaries or something similar)
Rephrasing the question:
I want to modify class Value (define some fields, write a constructor and write the method Value.SetValue(T value) ), then construct three different variables of type Value (A, B, C) in such a way that when I call Store.A.SetValue(42) the value Store<int>.A is changed to 42.
Another variation of the classes:
static class Holder<T> {
T Value { get; set; }
}
static class Store2<T> {
public static Holder<T> A = new Holder<T>();
public static Holder<T> B = new Holder<T>();
public static Holder<T> C = new Holder<T>();
}
public static class Store2 {
public static Value A = new Value2(Store2<>.A); //just an example of what I want
public static Value B = new Value2(Store2<>.B); //passing non-specific generic expression
public static Value C = new Value3({TFree}() => Store2<TFree>.C); //just an example of what I want
}
public class Value2 { //Non-generic class!
Holder{TFree}<TFree> _holder; //just an example of what I want
public Value(Holder{TFree}<TFree> holder) { //just an example of what I want
_holder = holder;
}
public void SetValue<T> (T value) {
_holder{T}.Value = value; //just an example of what I want
}
}
public class Value3 { //Non-generic class! (Another variation)
Func{TFree}<Holder<TFree>> _holderFactory; //just an example of what I want
public Value(Func{TFree}<Holder<TFree>> holderFactory) { //just an example of what I want
_holderFactory = holderFactory;
}
public void SetValue<T> (T value) {
Holder<T> holder = _holderFactory{T}(); //just an example of what I want
holder.Value = value;
}
}
Solution:
An easy reflection-free and collection-free solution was found using the answers to another question ( Emulating delegates with free generic type parameters in C# and Emulating delegates with free generic type parameters in C#). The solution is Delegates to generic operations where the generic type is unknown. How to create something like that?.
Use an array to store the values and access them through a property using an index
public static class Store<T>
{
public static readonly T[] Values = new T[3];
public static T A { get { return Values[0]; } set { Values[0] = value; } }
public static T B { get { return Values[1]; } set { Values[1] = value; } }
public static T C { get { return Values[2]; } set { Values[2] = value; } }
}
public static class Store
{
public static readonly Value A = new Value(0);
public static readonly Value B = new Value(1);
public static readonly Value C = new Value(2);
}
public class Value
{
private int _index;
public Value(int index)
{
_index = index;
}
public void SetValue<T>(T value)
{
Store<T>.Values[_index] = value;
}
public T GetValue<T>()
{
return Store<T>.Values[_index];
}
}
Since the constructor of Value is not aware of any generic type parameter, you cannot have any reference to a specific Store<T>.
UPDATE
Be aware of the fact that a copy of Store<T> will be created for every distinct type argument that you supplied for T. See this example
Store.A.SetValue(42);
Store.A.SetValue("Douglas Adams");
Store.A.SetValue(new DirectoryInfo(#"C:\"));
Store.A.SetValue(new List<int>());
var x1 = Store.A.GetValue<int>(); // --> 42
var x2 = Store.A.GetValue<string>(); // --> "Douglas Adams"
var x3 = Store.A.GetValue<DirectoryInfo>(); // --> DirectoryInfo{ C:\ }
var x4 = Store.A.GetValue<List<int>>(); // --> List<int>{ Count = 0 }
By using the debugger, you will see that four different values are stored in A at the same time! Of cause these are four differents A's that exist in four diffferent Store<T>.
The problem turned out to be solvable. Mike-z gave me a nearly right solution for the delegate-to-generic-method problem ( Emulating delegates with free generic type parameters in C#) which I modified to be a full solution: ( Emulating delegates with free generic type parameters in C#).
The solution this question becomes easy too. Interfaces can contain generic methods and we can use the interface-valued variables to store links to generic methods without specifying concrete type arguments. The following code utilizes the Store<T> class without modifications and uses the ISetter interface and ASetter/BSetter/CSetter "closures" to hold references to different generic members. The Value class stores the references in a ISetter-typed variable and uses the generic member which the _setter links to once the type argument T becomes available.
public interface ISetter {
void SetValue<T>(T value);
}
public static class Store {
public static Value A = new Value(new ASetter());
public static Value B = new Value(new BSetter());
public static Value C = new Value(new CSetter());
class ASetter : ISetter {
public void SetValue<T>(T value) { Store<T>.A = value; }
}
class BSetter : ISetter {
public void SetValue<T>(T value) { Store<T>.B = value; }
}
class CSetter : ISetter {
public void SetValue<T>(T value) { Store<T>.C = value; }
}
}
public class Value {
ISetter _setter;
public Value(ISetter setter) {
_setter = setter;
}
public void SetValue<T> (T value) {
_setter.SetValue<T>(value);
}
}

What's the equivalent of Java's enum in C#? [duplicate]

This question already has answers here:
C# vs Java Enum (for those new to C#)
(13 answers)
Closed 9 years ago.
What's the equivalent of Java's enum in C#?
Full Java enum functionality isn't available in C#. You can come reasonably close using nested types and a private constructor though. For example:
using System;
using System.Collections.Generic;
using System.Xml.Linq;
public abstract class Operator
{
public static readonly Operator Plus = new PlusOperator();
public static readonly Operator Minus =
new GenericOperator((x, y) => x - y);
public static readonly Operator Times =
new GenericOperator((x, y) => x * y);
public static readonly Operator Divide =
new GenericOperator((x, y) => x / y);
// Prevent other top-level types from instantiating
private Operator()
{
}
public abstract int Execute(int left, int right);
private class PlusOperator : Operator
{
public override int Execute(int left, int right)
{
return left + right;
}
}
private class GenericOperator : Operator
{
private readonly Func<int, int, int> op;
internal GenericOperator(Func<int, int, int> op)
{
this.op = op;
}
public override int Execute(int left, int right)
{
return op(left, right);
}
}
}
Of course you don't have to use nested types, but they give the handy "custom behaviour" part which Java enums are nice for. In other cases you can just pass arguments to a private constructor to get a well-known restricted set of values.
A few things this doesn't give you:
Ordinal support
Switch support
EnumSet
Serialization/deserialization (as a singleton)
Some of that could probably be done with enough effort, though switch wouldn't really be feasible without hackery. Now if the language did something like this, it could do interesting things to make switch work by making the hackery automatic (e.g. declaring a load of const fields automatically, and changing any switch over the enum type to a switch over integers, only allowing "known" cases .)
Oh, and partial types mean you don't have to have all of the enum values in the same file. If each value got quite involved (which is definitely possible) each could have its own file.
Enums are one of the few language features that is better implemented in java than c#.
In java, enums are full fledged named instances of a type, while c# enums are basically named constants.
That being said, for the basic case, they will look similar. However in java, you have more power, in that you can add behavior to the individual enums, as they are full fledged classes.
is there some feature in particular you are looking for?
Here's another interesting idea. I came up with the following Enumeration base class:
public abstract class Enumeration<T>
where T : Enumeration<T>
{
protected static int nextOrdinal = 0;
protected static readonly Dictionary<int, Enumeration<T>> byOrdinal = new Dictionary<int, Enumeration<T>>();
protected static readonly Dictionary<string, Enumeration<T>> byName = new Dictionary<string, Enumeration<T>>();
protected readonly string name;
protected readonly int ordinal;
protected Enumeration(string name)
: this (name, nextOrdinal)
{
}
protected Enumeration(string name, int ordinal)
{
this.name = name;
this.ordinal = ordinal;
nextOrdinal = ordinal + 1;
byOrdinal.Add(ordinal, this);
byName.Add(name, this);
}
public override string ToString()
{
return name;
}
public string Name
{
get { return name; }
}
public static explicit operator int(Enumeration<T> obj)
{
return obj.ordinal;
}
public int Ordinal
{
get { return ordinal; }
}
}
It's got a type parameter basically just so the ordinal count will work properly across different derived enumerations. Jon's Operator example above then becomes:
public class Operator : Enumeration<Operator>
{
public static readonly Operator Plus = new Operator("Plus", (x, y) => x + y);
public static readonly Operator Minus = new Operator("Minus", (x, y) => x - y);
public static readonly Operator Times = new Operator("Times", (x, y) => x * y);
public static readonly Operator Divide = new Operator("Divide", (x, y) => x / y);
private readonly Func<int, int, int> op;
// Prevent other top-level types from instantiating
private Operator(string name, Func<int, int, int> op)
:base (name)
{
this.op = op;
}
public int Execute(int left, int right)
{
return op(left, right);
}
}
This gives a few advantages.
Ordinal support
Conversion to string and int which makes switch statements feasible
GetType() will give the same result for each of the values of a derived Enumeration type.
The Static methods from System.Enum can be added to the base Enumeration class to allow the same functionality.
You could probably use the old typesafe enum pattern that we used in Java before we got real ones (assuming that the ones in C# really aren't classes as a comment claims). The pattern is described just before the middle of this page
//Review the sample enum below for a template on how to implement a JavaEnum.
//There is also an EnumSet implementation below.
public abstract class JavaEnum : IComparable {
public static IEnumerable<JavaEnum> Values {
get {
throw new NotImplementedException("Enumeration missing");
}
}
public readonly string Name;
public JavaEnum(string name) {
this.Name = name;
}
public override string ToString() {
return base.ToString() + "." + Name.ToUpper();
}
public int CompareTo(object obj) {
if(obj is JavaEnum) {
return string.Compare(this.Name, ((JavaEnum)obj).Name);
} else {
throw new ArgumentException();
}
}
//Dictionary values are of type SortedSet<T>
private static Dictionary<Type, object> enumDictionary;
public static SortedSet<T> RetrieveEnumValues<T>() where T : JavaEnum {
if(enumDictionary == null) {
enumDictionary = new Dictionary<Type, object>();
}
object enums;
if(!enumDictionary.TryGetValue(typeof(T), out enums)) {
enums = new SortedSet<T>();
FieldInfo[] myFieldInfo = typeof(T).GetFields(BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public);
foreach(FieldInfo f in myFieldInfo) {
if(f.FieldType == typeof(T)) {
((SortedSet<T>)enums).Add((T)f.GetValue(null));
}
}
enumDictionary.Add(typeof(T), enums);
}
return (SortedSet<T>)enums;
}
}
//Sample JavaEnum
public class SampleEnum : JavaEnum {
//Enum values
public static readonly SampleEnum A = new SampleEnum("A", 1);
public static readonly SampleEnum B = new SampleEnum("B", 2);
public static readonly SampleEnum C = new SampleEnum("C", 3);
//Variables or Properties common to all enums of this type
public int int1;
public static int int2 = 4;
public static readonly int int3 = 9;
//The Values property must be replaced with a call to JavaEnum.generateEnumValues<MyEnumType>() to generate an IEnumerable set.
public static new IEnumerable<SampleEnum> Values {
get {
foreach(var e in JavaEnum.RetrieveEnumValues<SampleEnum>()) {
yield return e;
}
//If this enum should compose several enums, add them here
//foreach(var e in ChildSampleEnum.Values) {
// yield return e;
//}
}
}
public SampleEnum(string name, int int1)
: base(name) {
this.int1 = int1;
}
}
public class EnumSet<T> : SortedSet<T> where T : JavaEnum {
// Creates an enum set containing all of the elements in the specified element type.
public static EnumSet<T> AllOf(IEnumerable<T> values) {
EnumSet<T> returnSet = new EnumSet<T>();
foreach(T item in values) {
returnSet.Add(item);
}
return returnSet;
}
// Creates an enum set with the same element type as the specified enum set, initially containing all the elements of this type that are not contained in the specified set.
public static EnumSet<T> ComplementOf(IEnumerable<T> values, EnumSet<T> set) {
EnumSet<T> returnSet = new EnumSet<T>();
foreach(T item in values) {
if(!set.Contains(item)) {
returnSet.Add(item);
}
}
return returnSet;
}
// Creates an enum set initially containing all of the elements in the range defined by the two specified endpoints.
public static EnumSet<T> Range(IEnumerable<T> values, T from, T to) {
EnumSet<T> returnSet = new EnumSet<T>();
if(from == to) {
returnSet.Add(from);
return returnSet;
}
bool isFrom = false;
foreach(T item in values) {
if(isFrom) {
returnSet.Add(item);
if(item == to) {
return returnSet;
}
} else if(item == from) {
isFrom = true;
returnSet.Add(item);
}
}
throw new ArgumentException();
}
// Creates an enum set initially containing the specified element(s).
public static EnumSet<T> Of(params T[] setItems) {
EnumSet<T> returnSet = new EnumSet<T>();
foreach(T item in setItems) {
returnSet.Add(item);
}
return returnSet;
}
// Creates an empty enum set with the specified element type.
public static EnumSet<T> NoneOf() {
return new EnumSet<T>();
}
// Returns a copy of the set passed in.
public static EnumSet<T> CopyOf(EnumSet<T> set) {
EnumSet<T> returnSet = new EnumSet<T>();
returnSet.Add(set);
return returnSet;
}
// Adds a set to an existing set.
public void Add(EnumSet<T> enumSet) {
foreach(T item in enumSet) {
this.Add(item);
}
}
// Removes a set from an existing set.
public void Remove(EnumSet<T> enumSet) {
foreach(T item in enumSet) {
this.Remove(item);
}
}
}
enum , or do you need something in particular that Java enums have but c# doesn't ?

String representation of an Enum

I have the following enumeration:
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
The problem however is that I need the word "FORMS" when I ask for AuthenticationMethod.FORMS and not the id 1.
I have found the following solution for this problem (link):
First I need to create a custom attribute called "StringValue":
public class StringValue : System.Attribute
{
private readonly string _value;
public StringValue(string value)
{
_value = value;
}
public string Value
{
get { return _value; }
}
}
Then I can add this attribute to my enumerator:
public enum AuthenticationMethod
{
[StringValue("FORMS")]
FORMS = 1,
[StringValue("WINDOWS")]
WINDOWSAUTHENTICATION = 2,
[StringValue("SSO")]
SINGLESIGNON = 3
}
And of course I need something to retrieve that StringValue:
public static class StringEnum
{
public static string GetStringValue(Enum value)
{
string output = null;
Type type = value.GetType();
//Check first in our cached results...
//Look for our 'StringValueAttribute'
//in the field's custom attributes
FieldInfo fi = type.GetField(value.ToString());
StringValue[] attrs =
fi.GetCustomAttributes(typeof(StringValue),
false) as StringValue[];
if (attrs.Length > 0)
{
output = attrs[0].Value;
}
return output;
}
}
Good now I've got the tools to get a string value for an enumerator.
I can then use it like this:
string valueOfAuthenticationMethod = StringEnum.GetStringValue(AuthenticationMethod.FORMS);
Okay now all of these work like a charm but I find it a whole lot of work. I was wondering if there is a better solution for this.
I also tried something with a dictionary and static properties but that wasn't better either.
Try type-safe-enum pattern.
public sealed class AuthenticationMethod {
private readonly String name;
private readonly int value;
public static readonly AuthenticationMethod FORMS = new AuthenticationMethod (1, "FORMS");
public static readonly AuthenticationMethod WINDOWSAUTHENTICATION = new AuthenticationMethod (2, "WINDOWS");
public static readonly AuthenticationMethod SINGLESIGNON = new AuthenticationMethod (3, "SSN");
private AuthenticationMethod(int value, String name){
this.name = name;
this.value = value;
}
public override String ToString(){
return name;
}
}
Update
Explicit (or implicit) type conversion can be done by
adding static field with mapping
private static readonly Dictionary<string, AuthenticationMethod> instance = new Dictionary<string,AuthenticationMethod>();
n.b. In order that the initialisation of the the "enum member" fields doesn't throw a NullReferenceException when calling the instance constructor, be sure to put the Dictionary field before the "enum member" fields in your class. This is because static field initialisers are called in declaration order, and before the static constructor, creating the weird and necessary but confusing situation that the instance constructor can be called before all static fields have been initialised, and before the static constructor is called.
filling this mapping in instance constructor
instance[name] = this;
and adding user-defined type conversion operator
public static explicit operator AuthenticationMethod(string str)
{
AuthenticationMethod result;
if (instance.TryGetValue(str, out result))
return result;
else
throw new InvalidCastException();
}
Use method
Enum.GetName(Type MyEnumType, object enumvariable)
as in (Assume Shipper is a defined Enum)
Shipper x = Shipper.FederalExpress;
string s = Enum.GetName(typeof(Shipper), x);
There are a bunch of other static methods on the Enum class worth investigating too...
You can reference the name rather than the value by using ToString()
Console.WriteLine("Auth method: {0}", AuthenticationMethod.Forms.ToString());
The documentation is here:
http://msdn.microsoft.com/en-us/library/16c1xs4z.aspx
...and if you name your enums in Pascal Case (as I do - such as ThisIsMyEnumValue = 1 etc.) then you could use a very simple regex to print the friendly form:
static string ToFriendlyCase(this string EnumString)
{
return Regex.Replace(EnumString, "(?!^)([A-Z])", " $1");
}
which can easily be called from any string:
Console.WriteLine("ConvertMyCrazyPascalCaseSentenceToFriendlyCase".ToFriendlyCase());
Outputs:
Convert My Crazy Pascal Case Sentence To Friendly Case
That saves running all the way around the houses creating custom attributes and attaching them to your enums or using lookup tables to marry an enum value with a friendly string and best of all it's self managing and can be used on any Pascal Case string which is infinitely more reusable. Of course, it doesn't allow you to have a different friendly name than your enum which your solution does provide.
I do like your original solution though for more complex scenarios though. You could take your solution one step further and make your GetStringValue an extension method of your enum and then you wouldn't need to reference it like StringEnum.GetStringValue...
public static string GetStringValue(this AuthenticationMethod value)
{
string output = null;
Type type = value.GetType();
FieldInfo fi = type.GetField(value.ToString());
StringValue[] attrs = fi.GetCustomAttributes(typeof(StringValue), false) as StringValue[];
if (attrs.Length > 0)
output = attrs[0].Value;
return output;
}
You could then access it easily straight from your enum instance:
Console.WriteLine(AuthenticationMethod.SSO.GetStringValue());
Unfortunately reflection to get attributes on enums is quite slow:
See this question: Anyone know a quick way to get to custom attributes on an enum value?
The .ToString() is quite slow on enums too.
You can write extension methods for enums though:
public static string GetName( this MyEnum input ) {
switch ( input ) {
case MyEnum.WINDOWSAUTHENTICATION:
return "Windows";
//and so on
}
}
This isn't great, but will be quick and not require the reflection for attributes or field name.
C#6 Update
If you can use C#6 then the new nameof operator works for enums, so nameof(MyEnum.WINDOWSAUTHENTICATION) will be converted to "WINDOWSAUTHENTICATION" at compile time, making it the quickest way to get enum names.
Note that this will convert the explicit enum to an inlined constant, so it doesn't work for enums that you have in a variable. So:
nameof(AuthenticationMethod.FORMS) == "FORMS"
But...
var myMethod = AuthenticationMethod.FORMS;
nameof(myMethod) == "myMethod"
I use an extension method:
public static class AttributesHelperExtension
{
public static string ToDescription(this Enum value)
{
var da = (DescriptionAttribute[])(value.GetType().GetField(value.ToString())).GetCustomAttributes(typeof(DescriptionAttribute), false);
return da.Length > 0 ? da[0].Description : value.ToString();
}
}
Now decorate the enum with:
public enum AuthenticationMethod
{
[Description("FORMS")]
FORMS = 1,
[Description("WINDOWSAUTHENTICATION")]
WINDOWSAUTHENTICATION = 2,
[Description("SINGLESIGNON ")]
SINGLESIGNON = 3
}
When you call
AuthenticationMethod.FORMS.ToDescription() you will get "FORMS".
Just use the ToString() method
public enum any{Tomato=0,Melon,Watermelon}
To reference the string Tomato, just use
any.Tomato.ToString();
Very simple solution to this with .Net 4.0 and above. No other code is needed.
public enum MyStatus
{
Active = 1,
Archived = 2
}
To get the string about just use:
MyStatus.Active.ToString("f");
or
MyStatus.Archived.ToString("f");`
The value will be "Active" or "Archived".
To see the different string formats (the "f" from above) when calling Enum.ToString see this Enumeration Format Strings page
I use the Description attribute from the System.ComponentModel namespace. Simply decorate the enum and then use this code to retrieve it:
public static string GetDescription<T>(this object enumerationValue)
where T : struct
{
Type type = enumerationValue.GetType();
if (!type.IsEnum)
{
throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
}
//Tries to find a DescriptionAttribute for a potential friendly name
//for the enum
MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
if (memberInfo != null && memberInfo.Length > 0)
{
object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attrs != null && attrs.Length > 0)
{
//Pull out the description value
return ((DescriptionAttribute)attrs[0]).Description;
}
}
//If we have no description attribute, just return the ToString of the enum
return enumerationValue.ToString();
}
As an example:
public enum Cycle : int
{
[Description("Daily Cycle")]
Daily = 1,
Weekly,
Monthly
}
This code nicely caters for enums where you don't need a "Friendly name" and will return just the .ToString() of the enum.
I really like Jakub Šturc's answer, but it's shortcoming is that you cannot use it with a switch-case statement. Here's a slightly modified version of his answer that can be used with a switch statement:
public sealed class AuthenticationMethod
{
#region This code never needs to change.
private readonly string _name;
public readonly Values Value;
private AuthenticationMethod(Values value, String name){
this._name = name;
this.Value = value;
}
public override String ToString(){
return _name;
}
#endregion
public enum Values
{
Forms = 1,
Windows = 2,
SSN = 3
}
public static readonly AuthenticationMethod FORMS = new AuthenticationMethod (Values.Forms, "FORMS");
public static readonly AuthenticationMethod WINDOWSAUTHENTICATION = new AuthenticationMethod (Values.Windows, "WINDOWS");
public static readonly AuthenticationMethod SINGLESIGNON = new AuthenticationMethod (Values.SSN, "SSN");
}
So you get all of the benefits of Jakub Šturc's answer, plus we can use it with a switch statement like so:
var authenticationMethodVariable = AuthenticationMethod.FORMS; // Set the "enum" value we want to use.
var methodName = authenticationMethodVariable.ToString(); // Get the user-friendly "name" of the "enum" value.
// Perform logic based on which "enum" value was chosen.
switch (authenticationMethodVariable.Value)
{
case authenticationMethodVariable.Values.Forms: // Do something
break;
case authenticationMethodVariable.Values.Windows: // Do something
break;
case authenticationMethodVariable.Values.SSN: // Do something
break;
}
I use a combination of several of the suggestions above, combined with some caching. Now, I got the idea from some code that I found somewhere on the net, but I can neither remember where I got it or find it. So if anyone ever finds something that looks similar please comment with the attribution.
Anyway, the usage involves the type converters, so if you are binding to the UI it 'just works'. You can extended with Jakub's pattern for quick code lookup by initializing from the type converter into the static methods.
The base usage would look like this
[TypeConverter(typeof(CustomEnumTypeConverter<MyEnum>))]
public enum MyEnum
{
// The custom type converter will use the description attribute
[Description("A custom description")]
ValueWithCustomDescription,
// This will be exposed exactly.
Exact
}
The code for the custom enum type converter follows:
public class CustomEnumTypeConverter<T> : EnumConverter
where T : struct
{
private static readonly Dictionary<T,string> s_toString =
new Dictionary<T, string>();
private static readonly Dictionary<string, T> s_toValue =
new Dictionary<string, T>();
private static bool s_isInitialized;
static CustomEnumTypeConverter()
{
System.Diagnostics.Debug.Assert(typeof(T).IsEnum,
"The custom enum class must be used with an enum type.");
}
public CustomEnumTypeConverter() : base(typeof(T))
{
if (!s_isInitialized)
{
Initialize();
s_isInitialized = true;
}
}
protected void Initialize()
{
foreach (T item in Enum.GetValues(typeof(T)))
{
string description = GetDescription(item);
s_toString[item] = description;
s_toValue[description] = item;
}
}
private static string GetDescription(T optionValue)
{
var optionDescription = optionValue.ToString();
var optionInfo = typeof(T).GetField(optionDescription);
if (Attribute.IsDefined(optionInfo, typeof(DescriptionAttribute)))
{
var attribute =
(DescriptionAttribute)Attribute.
GetCustomAttribute(optionInfo, typeof(DescriptionAttribute));
return attribute.Description;
}
return optionDescription;
}
public override object ConvertTo(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture,
object value, Type destinationType)
{
var optionValue = (T)value;
if (destinationType == typeof(string) &&
s_toString.ContainsKey(optionValue))
{
return s_toString[optionValue];
}
return base.ConvertTo(context, culture, value, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value)
{
var stringValue = value as string;
if (!string.IsNullOrEmpty(stringValue) && s_toValue.ContainsKey(stringValue))
{
return s_toValue[stringValue];
}
return base.ConvertFrom(context, culture, value);
}
}
}
In your question you never said that you actually need the numeric value of the enum anywhere.
If you do not and just need an enum of type string (which is not an integral type so can not be a base of enum) here is a way:
static class AuthenticationMethod
{
public static readonly string
FORMS = "Forms",
WINDOWSAUTHENTICATION = "WindowsAuthentication";
}
you can use the same syntax as enum to reference it
if (bla == AuthenticationMethod.FORMS)
It will be a bit slower than with numeric values (comparing strings instead of numbers) but on the plus side it is not using reflection (slow) to access the string.
Update: Visiting this page, 8 years later, after not touching C# for a long while, looks like my answer is no longer the best solution. I really like the converter solution tied with attribute-functions.
If you are reading this, please make sure you also check out other answers. (hint: they are above this one)
As most of you, I really liked the selected answer by Jakub Šturc, but I also really hate to copy-paste code, and try to do it as little as I can.
So I decided I wanted an EnumBase class from which most of the functionality is inherited/built-in, leaving me to focus on the content instead of behavior.
The main problem with this approach is based on the fact that although Enum values are type-safe instances, the interaction is with the Static implementation of the Enum Class type.
So with a little help of generics magic, I think I finally got the correct mix.
Hope someone finds this as useful as I did.
I'll start with Jakub's example, but using inheritance and generics:
public sealed class AuthenticationMethod : EnumBase<AuthenticationMethod, int>
{
public static readonly AuthenticationMethod FORMS =
new AuthenticationMethod(1, "FORMS");
public static readonly AuthenticationMethod WINDOWSAUTHENTICATION =
new AuthenticationMethod(2, "WINDOWS");
public static readonly AuthenticationMethod SINGLESIGNON =
new AuthenticationMethod(3, "SSN");
private AuthenticationMethod(int Value, String Name)
: base( Value, Name ) { }
public new static IEnumerable<AuthenticationMethod> All
{ get { return EnumBase<AuthenticationMethod, int>.All; } }
public static explicit operator AuthenticationMethod(string str)
{ return Parse(str); }
}
And here is the base class:
using System;
using System.Collections.Generic;
using System.Linq; // for the .AsEnumerable() method call
// E is the derived type-safe-enum class
// - this allows all static members to be truly unique to the specific
// derived class
public class EnumBase<E, T> where E: EnumBase<E, T>
{
#region Instance code
public T Value { get; private set; }
public string Name { get; private set; }
protected EnumBase(T EnumValue, string Name)
{
Value = EnumValue;
this.Name = Name;
mapping.Add(Name, this);
}
public override string ToString() { return Name; }
#endregion
#region Static tools
static private readonly Dictionary<string, EnumBase<E, T>> mapping;
static EnumBase() { mapping = new Dictionary<string, EnumBase<E, T>>(); }
protected static E Parse(string name)
{
EnumBase<E, T> result;
if (mapping.TryGetValue(name, out result))
{
return (E)result;
}
throw new InvalidCastException();
}
// This is protected to force the child class to expose it's own static
// method.
// By recreating this static method at the derived class, static
// initialization will be explicit, promising the mapping dictionary
// will never be empty when this method is called.
protected static IEnumerable<E> All
{ get { return mapping.Values.AsEnumerable().Cast<E>(); } }
#endregion
}
How I solved this as an extension method:
using System.ComponentModel;
public static string GetDescription(this Enum value)
{
var descriptionAttribute = (DescriptionAttribute)value.GetType()
.GetField(value.ToString())
.GetCustomAttributes(false)
.Where(a => a is DescriptionAttribute)
.FirstOrDefault();
return descriptionAttribute != null ? descriptionAttribute.Description : value.ToString();
}
Enum:
public enum OrderType
{
None = 0,
[Description("New Card")]
NewCard = 1,
[Description("Reload")]
Refill = 2
}
Usage (where o.OrderType is a property with the same name as the enum):
o.OrderType.GetDescription()
Which gives me a string of "New Card" or "Reload" instead of the actual enum value NewCard and Refill.
If you've come here looking to implement a simple "Enum" but whose values are strings instead of ints, here is the simplest solution:
public sealed class MetricValueList
{
public static readonly string Brand = "A4082457-D467-E111-98DC-0026B9010912";
public static readonly string Name = "B5B5E167-D467-E111-98DC-0026B9010912";
}
Implementation:
var someStringVariable = MetricValueList.Brand;
I agree with Keith, but I can't vote up (yet).
I use a static method and swith statement to return exactly what I want. In the database I store tinyint and my code only uses the actual enum, so the strings are for UI requirements. After numerous testing this resulted in the best performance and most control over the output.
public static string ToSimpleString(this enum)
{
switch (enum)
{
case ComplexForms:
return "ComplexForms";
break;
}
}
public static string ToFormattedString(this enum)
{
switch (enum)
{
case ComplexForms:
return "Complex Forms";
break;
}
}
However, by some accounts, this leads to a possible maintenance nightmare and some code smell. I try to keep an eye for enums that are long and a lot of enums, or those that change frequently. Otherwise, this has been a great solution for me.
When I'm confronted with this problem, there are a couple of questions that I try to find the answers to first:
Are the names of my enum values sufficiently friendly for the purpose, or do I need to provide friendlier ones?
Do I need to round-trip? That is, will I need to take text values and parse them into enum values?
Is this something I need to do for many enums in my project, or just one?
What kind of UI elements will I be presenting this information in - in particular, will I be binding to the UI, or using property sheets?
Does this need to be localizable?
The simplest way to do this is with Enum.GetValue (and support round-tripping using Enum.Parse). It's also often worth building a TypeConverter, as Steve Mitcham suggests, to support UI binding. (It's not necessary to build a TypeConverter when you're using property sheets, which is one of the nice things about property sheets. Though lord knows they have their own issues.)
In general, if the answers to the above questions suggest that's not going to work, my next step is to create and populate a static Dictionary<MyEnum, string>, or possibly a Dictionary<Type, Dictionary<int, string>>. I tend to skip the intermediate decorate-the-code-with-attributes step because what's usually coming down the pike next is the need to change the friendly values after deployment (often, but not always, because of localization).
I created a base class for creating string-valued enums in .NET. It is just one C# file that you can copy & paste into your projects, or install via NuGet package named StringEnum. GitHub Repo
Intellisense will suggest the enum name if the class is annotated with the xml comment <completitionlist>. (Works in both C# and VB)
Usage similar to a regular enum:
///<completionlist cref="HexColor"/>
class HexColor : StringEnum<HexColor>
{
public static readonly HexColor Blue = Create("#FF0000");
public static readonly HexColor Green = Create("#00FF00");
public static readonly HexColor Red = Create("#000FF");
}
// Static Parse Method
HexColor.Parse("#FF0000") // => HexColor.Red
HexColor.Parse("#ff0000", caseSensitive: false) // => HexColor.Red
HexColor.Parse("invalid") // => throws InvalidOperationException
// Static TryParse method.
HexColor.TryParse("#FF0000") // => HexColor.Red
HexColor.TryParse("#ff0000", caseSensitive: false) // => HexColor.Red
HexColor.TryParse("invalid") // => null
// Parse and TryParse returns the preexistent instances
object.ReferenceEquals(HexColor.Parse("#FF0000"), HexColor.Red) // => true
// Conversion from your `StringEnum` to `string`
string myString1 = HexColor.Red.ToString(); // => "#FF0000"
string myString2 = HexColor.Red; // => "#FF0000" (implicit cast)
Instalation:
Paste the following StringEnum base class to your project. (latest version)
Or install StringEnum NuGet package, which is based on .Net Standard 1.0 so it runs on .Net Core >= 1.0, .Net Framework >= 4.5, Mono >= 4.6, etc.
/// <summary>
/// Base class for creating string-valued enums in .NET.<br/>
/// Provides static Parse() and TryParse() methods and implicit cast to string.
/// </summary>
/// <example>
/// <code>
/// class Color : StringEnum <Color>
/// {
/// public static readonly Color Blue = Create("Blue");
/// public static readonly Color Red = Create("Red");
/// public static readonly Color Green = Create("Green");
/// }
/// </code>
/// </example>
/// <typeparam name="T">The string-valued enum type. (i.e. class Color : StringEnum<Color>)</typeparam>
public abstract class StringEnum<T> : IEquatable<T> where T : StringEnum<T>, new()
{
protected string Value;
private static Dictionary<string, T> valueDict = new Dictionary<string, T>();
protected static T Create(string value)
{
if (value == null)
return null; // the null-valued instance is null.
var result = new T() { Value = value };
valueDict.Add(value, result);
return result;
}
public static implicit operator string(StringEnum<T> enumValue) => enumValue.Value;
public override string ToString() => Value;
public static bool operator !=(StringEnum<T> o1, StringEnum<T> o2) => o1?.Value != o2?.Value;
public static bool operator ==(StringEnum<T> o1, StringEnum<T> o2) => o1?.Value == o2?.Value;
public override bool Equals(object other) => this.Value.Equals((other as T)?.Value ?? (other as string));
bool IEquatable<T>.Equals(T other) => this.Value.Equals(other.Value);
public override int GetHashCode() => Value.GetHashCode();
/// <summary>
/// Parse the <paramref name="value"/> specified and returns a valid <typeparamref name="T"/> or else throws InvalidOperationException.
/// </summary>
/// <param name="value">The string value representad by an instance of <typeparamref name="T"/>. Matches by string value, not by the member name.</param>
/// <param name="caseSensitive">If true, the strings must match case and takes O(log n). False allows different case but is little bit slower (O(n))</param>
public static T Parse(string value, bool caseSensitive = true)
{
var result = TryParse(value, caseSensitive);
if (result == null)
throw new InvalidOperationException((value == null ? "null" : $"'{value}'") + $" is not a valid {typeof(T).Name}");
return result;
}
/// <summary>
/// Parse the <paramref name="value"/> specified and returns a valid <typeparamref name="T"/> or else returns null.
/// </summary>
/// <param name="value">The string value representad by an instance of <typeparamref name="T"/>. Matches by string value, not by the member name.</param>
/// <param name="caseSensitive">If true, the strings must match case. False allows different case but is slower: O(n)</param>
public static T TryParse(string value, bool caseSensitive = true)
{
if (value == null) return null;
if (valueDict.Count == 0) System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(T).TypeHandle); // force static fields initialization
if (caseSensitive)
{
if (valueDict.TryGetValue(value, out T item))
return item;
else
return null;
}
else
{
// slower O(n) case insensitive search
return valueDict.FirstOrDefault(f => f.Key.Equals(value, StringComparison.OrdinalIgnoreCase)).Value;
// Why Ordinal? => https://esmithy.net/2007/10/15/why-stringcomparisonordinal-is-usually-the-right-choice/
}
}
}
I wanted to post this as a comment to the post quoted below but couldn't because I don't have enough rep. The code contained an error and I wanted to point this out to individuals trying to use this solution:
[TypeConverter(typeof(CustomEnumTypeConverter(typeof(MyEnum))]
public enum MyEnum
{
// The custom type converter will use the description attribute
[Description("A custom description")]
ValueWithCustomDescription,
// This will be exposed exactly.
Exact
}
should be
[TypeConverter(typeof(CustomEnumTypeConverter<MyEnum>))]
public enum MyEnum
{
// The custom type converter will use the description attribute
[Description("A custom description")]
ValueWithCustomDescription,
// This will be exposed exactly.
Exact
}
My variant
public struct Colors
{
private String current;
private static string red = "#ff0000";
private static string green = "#00ff00";
private static string blue = "#0000ff";
private static IList<String> possibleColors;
public static Colors Red { get { return (Colors) red; } }
public static Colors Green { get { return (Colors) green; } }
public static Colors Blue { get { return (Colors) blue; } }
static Colors()
{
possibleColors = new List<string>() {red, green, blue};
}
public static explicit operator String(Colors value)
{
return value.current;
}
public static explicit operator Colors(String value)
{
if (!possibleColors.Contains(value))
{
throw new InvalidCastException();
}
Colors color = new Colors();
color.current = value;
return color;
}
public static bool operator ==(Colors left, Colors right)
{
return left.current == right.current;
}
public static bool operator !=(Colors left, Colors right)
{
return left.current != right.current;
}
public bool Equals(Colors other)
{
return Equals(other.current, current);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (obj.GetType() != typeof(Colors)) return false;
return Equals((Colors)obj);
}
public override int GetHashCode()
{
return (current != null ? current.GetHashCode() : 0);
}
public override string ToString()
{
return current;
}
}
Code looks a bit ugly, but usages of this struct are pretty presentative.
Colors color1 = Colors.Red;
Console.WriteLine(color1); // #ff0000
Colors color2 = (Colors) "#00ff00";
Console.WriteLine(color2); // #00ff00
// Colors color3 = "#0000ff"; // Compilation error
// String color4 = Colors.Red; // Compilation error
Colors color5 = (Colors)"#ff0000";
Console.WriteLine(color1 == color5); // True
Colors color6 = (Colors)"#00ff00";
Console.WriteLine(color1 == color6); // False
Also, I think, if a lot of such enums required, code generation (e.g. T4) might be used.
Option 1:
public sealed class FormsAuth
{
public override string ToString{return "Forms Authtentication";}
}
public sealed class WindowsAuth
{
public override string ToString{return "Windows Authtentication";}
}
public sealed class SsoAuth
{
public override string ToString{return "SSO";}
}
and then
object auth = new SsoAuth(); //or whatever
//...
//...
// blablabla
DoSomethingWithTheAuth(auth.ToString());
Option 2:
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
public class MyClass
{
private Dictionary<AuthenticationMethod, String> map = new Dictionary<AuthenticationMethod, String>();
public MyClass()
{
map.Add(AuthenticationMethod.FORMS,"Forms Authentication");
map.Add(AuthenticationMethod.WINDOWSAUTHENTICATION ,"Windows Authentication");
map.Add(AuthenticationMethod.SINGLESIGNON ,"SSo Authentication");
}
}
If you think about the problem we're trying to solve, it's not an enum we need at all. We need an object that allows a certain number of values to be associated with eachother; in other words, to define a class.
Jakub Šturc's type-safe enum pattern is the best option I see here.
Look at it:
It has a private constructor so only the class itself can define the allowed values.
It is a sealed class so values can't be modifed through inheritence.
It is type-safe, allowing your methods to require only that type.
There is no reflection performance hit incurred by accessing the values.
And lastly, it can be modified to associate more than two fields together, for example a Name, Description, and a numeric Value.
for me, the pragmatic approach is class inside class, sample:
public class MSEModel
{
class WITS
{
public const string DATE = "5005";
public const string TIME = "5006";
public const string MD = "5008";
public const string ROP = "5075";
public const string WOB = "5073";
public const string RPM = "7001";
...
}
Here is yet another way to accomplish the task of associating strings with enums:
struct DATABASE {
public enum enums {NOTCONNECTED, CONNECTED, ERROR}
static List<string> strings =
new List<string>() {"Not Connected", "Connected", "Error"};
public string GetString(DATABASE.enums value) {
return strings[(int)value];
}
}
This method is called like this:
public FormMain() {
DATABASE dbEnum;
string enumName = dbEnum.GetString(DATABASE.enums.NOTCONNECTED);
}
You can group related enums in their own struct. Since this method uses the enum type, you can use Intellisense to display the list of enums when making the GetString() call.
You can optionally use the new operator on the DATABASE struct. Not using it means the strings List is not allocated until the first GetString() call is made.
A lot of great answers here but in my case did not solve what I wanted out of an "string enum", which was:
Usable in a switch statement e.g switch(myEnum)
Can be used in function parameters e.g. foo(myEnum type)
Can be referenced e.g. myEnum.FirstElement
I can use strings e.g. foo("FirstElement") == foo(myEnum.FirstElement)
1,2 & 4 can actually be solved with a C# Typedef of a string (since strings are switchable in c#)
3 can be solved by static const strings. So if you have the same needs, this is the simplest approach:
public sealed class Types
{
private readonly String name;
private Types(String name)
{
this.name = name;
}
public override String ToString()
{
return name;
}
public static implicit operator Types(string str)
{
return new Types(str);
}
public static implicit operator string(Types str)
{
return str.ToString();
}
#region enum
public const string DataType = "Data";
public const string ImageType = "Image";
public const string Folder = "Folder";
#endregion
}
This allows for example:
public TypeArgs(Types SelectedType)
{
Types SelectedType = SelectedType
}
and
public TypeObject CreateType(Types type)
{
switch (type)
{
case Types.ImageType:
//
break;
case Types.DataType:
//
break;
}
}
Where CreateType can be called with a string or a type. However the downside is that any string is automatically a valid enum, this could be modified but then it would require some kind of init function...or possibly make they explicit cast internal?
Now if an int value was important to you (perhaps for comparison speed), you could use some ideas from Jakub Šturc fantastic answer and do something a bit crazy, this is my stab at it:
public sealed class Types
{
private static readonly Dictionary<string, Types> strInstance = new Dictionary<string, Types>();
private static readonly Dictionary<int, Types> intInstance = new Dictionary<int, Types>();
private readonly String name;
private static int layerTypeCount = 0;
private int value;
private Types(String name)
{
this.name = name;
value = layerTypeCount++;
strInstance[name] = this;
intInstance[value] = this;
}
public override String ToString()
{
return name;
}
public static implicit operator Types(int val)
{
Types result;
if (intInstance.TryGetValue(val, out result))
return result;
else
throw new InvalidCastException();
}
public static implicit operator Types(string str)
{
Types result;
if (strInstance.TryGetValue(str, out result))
{
return result;
}
else
{
result = new Types(str);
return result;
}
}
public static implicit operator string(Types str)
{
return str.ToString();
}
public static bool operator ==(Types a, Types b)
{
return a.value == b.value;
}
public static bool operator !=(Types a, Types b)
{
return a.value != b.value;
}
#region enum
public const string DataType = "Data";
public const string ImageType = "Image";
#endregion
}
but of course "Types bob = 4;" would be meaningless unless you had initialized them first which would sort of defeat the point...
But in theory TypeA == TypeB would be quicker...
If I'm understanding you correctly, you can simply use .ToString() to retrieve the name of the enum from the value (Assuming it's already cast as the Enum);
If you had the naked int (lets say from a database or something) you can first cast it to the enum.
Both methods below will get you the enum name.
AuthenticationMethod myCurrentSetting = AuthenticationMethod.FORMS;
Console.WriteLine(myCurrentSetting); // Prints: FORMS
string name = Enum.GetNames(typeof(AuthenticationMethod))[(int)myCurrentSetting-1];
Console.WriteLine(name); // Prints: FORMS
Keep in mind though, the second technique assumes you are using ints and your index is 1 based (not 0 based). The function GetNames also is quite heavy by comparison, you are generating a whole array each time it's called.
As you can see in the first technique, .ToString() is actually called implicitly.
Both of these are already mentioned in the answers of course, I'm just trying to clarify the differences between them.
old post but...
The answer to this may actually be very simple. Use Enum.ToString() function
There are 6 overloads of this function, you can use Enum.Tostring("F") or Enum.ToString() to return the string value. No need to bother with anything else. Here is a working Demo
Note that this solution may not work for all compilers (this demo does not work as expected) but at least it works for the latest compiler.
based on the MSDN: http://msdn.microsoft.com/en-us/library/cc138362.aspx
foreach (string str in Enum.GetNames(typeof(enumHeaderField)))
{
Debug.WriteLine(str);
}
str will be the names of the fields
Well, after reading all of the above I feel that the guys have over complicated the issue of transforming enumerators into strings.
I liked the idea of having attributes over enumerated fields but i think that attributes are mainly used for Meta-data, but in your case i think that all you need is some sort of localization.
public enum Color
{ Red = 1, Green = 2, Blue = 3}
public static EnumUtils
{
public static string GetEnumResourceString(object enumValue)
{
Type enumType = enumValue.GetType();
string value = Enum.GetName(enumValue.GetType(), enumValue);
string resourceKey = String.Format("{0}_{1}", enumType.Name, value);
string result = Resources.Enums.ResourceManager.GetString(resourceKey);
if (string.IsNullOrEmpty(result))
{
result = String.Format("{0}", value);
}
return result;
}
}
Now if we try to call the above method we can call it this way
public void Foo()
{
var col = Color.Red;
Console.WriteLine (EnumUtils.GetEnumResourceString (col));
}
All you need to do is just create a resource file containing all the enumerator values and the corresponding strings
Resource Name Resource Value
Color_Red My String Color in Red
Color_Blue Blueeey
Color_Green Hulk Color
What is actually very nice about that is that it will be very helpful if you need your application to be localized, since all you need to do is just create another resource file with your new language! and Voe-la!
When I am in a situation like that I propose the solution below.
And as a consuming class you could have
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyApp.Dictionaries
{
class Greek
{
public static readonly string Alpha = "Alpha";
public static readonly string Beta = "Beta";
public static readonly string Gamma = "Gamma";
public static readonly string Delta = "Delta";
private static readonly BiDictionary<int, string> Dictionary = new BiDictionary<int, string>();
static Greek() {
Dictionary.Add(1, Alpha);
Dictionary.Add(2, Beta);
Dictionary.Add(3, Gamma);
Dictionary.Add(4, Delta);
}
public static string getById(int id){
return Dictionary.GetByFirst(id);
}
public static int getByValue(string value)
{
return Dictionary.GetBySecond(value);
}
}
}
And using a bidirectional dictionary:
Based on this (https://stackoverflow.com/a/255638/986160) assuming that the keys will be associated with single values in the dictionary and similar to (https://stackoverflow.com/a/255630/986160) but a bit more elegant. This dictionary is also enumerable and you can go back and forth from ints to strings. Also you don't have to have any string in your codebase with the exception of this class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace MyApp.Dictionaries
{
class BiDictionary<TFirst, TSecond> : IEnumerable
{
IDictionary<TFirst, TSecond> firstToSecond = new Dictionary<TFirst, TSecond>();
IDictionary<TSecond, TFirst> secondToFirst = new Dictionary<TSecond, TFirst>();
public void Add(TFirst first, TSecond second)
{
firstToSecond.Add(first, second);
secondToFirst.Add(second, first);
}
public TSecond this[TFirst first]
{
get { return GetByFirst(first); }
}
public TFirst this[TSecond second]
{
get { return GetBySecond(second); }
}
public TSecond GetByFirst(TFirst first)
{
return firstToSecond[first];
}
public TFirst GetBySecond(TSecond second)
{
return secondToFirst[second];
}
public IEnumerator GetEnumerator()
{
return GetFirstEnumerator();
}
public IEnumerator GetFirstEnumerator()
{
return firstToSecond.GetEnumerator();
}
public IEnumerator GetSecondEnumerator()
{
return secondToFirst.GetEnumerator();
}
}
}
For larger string enum sets, the listed examples can become tiresome. If you want a list of status codes, or a list of other string based enums, an attribute system is annoying to use, and a static class with instances of itself is annoying to configure. For my own solution, I make use of T4 templating to make it easier to have string-backed enums. The result comes out similar to how the HttpMethod class works.
You can use it like this:
string statusCode = ResponseStatusCode.SUCCESS; // Automatically converts to string when needed
ResponseStatusCode codeByValueOf = ResponseStatusCode.ValueOf(statusCode); // Returns null if not found
// Implements TypeConverter so you can use it with string conversion methods.
var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(ResponseStatusCode));
ResponseStatusCode code = (ResponseStatusCode) converter.ConvertFromInvariantString(statusCode);
// You can get a full list of the values
bool canIterateOverValues = ResponseStatusCode.Values.Any();
// Comparisons are by value of the "Name" property. Not by memory pointer location.
bool implementsByValueEqualsEqualsOperator = "SUCCESS" == ResponseStatusCode.SUCCESS;
You start out with a Enum.tt file.
<## include file="StringEnum.ttinclude" #>
<#+
public static class Configuration
{
public static readonly string Namespace = "YourName.Space";
public static readonly string EnumName = "ResponseStatusCode";
public static readonly bool IncludeComments = true;
public static readonly object Nodes = new
{
SUCCESS = "The response was successful.",
NON_SUCCESS = "The request was not successful.",
RESOURCE_IS_DISCONTINUED = "The resource requested has been discontinued and can no longer be accessed."
};
}
#>
Then, you add in your StringEnum.ttinclude file.
<## template debug="false" hostspecific="false" language="C#" #>
<## assembly name="System.Core" #>
<## import namespace="System" #>
<## import namespace="System.Linq" #>
<## import namespace="System.Text" #>
<## import namespace="System.Reflection" #>
<## import namespace="System.Collections.Generic" #>
<## output extension=".cs" #>
<## CleanupBehavior processor="T4VSHost" CleanupAfterProcessingtemplate="true" #>
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
namespace <#= Configuration.Namespace #>
{
/// <summary>
/// TypeConverter implementations allow you to use features like string.ToNullable(T).
/// </summary>
public class <#= Configuration.EnumName #>TypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var casted = value as string;
if (casted != null)
{
var result = <#= Configuration.EnumName #>.ValueOf(casted);
if (result != null)
{
return result;
}
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
var casted = value as <#= Configuration.EnumName #>;
if (casted != null && destinationType == typeof(string))
{
return casted.ToString();
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
[TypeConverter(typeof(<#= Configuration.EnumName #>TypeConverter))]
public class <#= Configuration.EnumName #> : IEquatable<<#= Configuration.EnumName #>>
{
//---------------------------------------------------------------------------------------------------
// V A L U E S _ L I S T
//---------------------------------------------------------------------------------------------------
<# Write(Helpers.PrintEnumProperties(Configuration.Nodes)); #>
private static List<<#= Configuration.EnumName #>> _list { get; set; } = null;
public static List<<#= Configuration.EnumName #>> ToList()
{
if (_list == null)
{
_list = typeof(<#= Configuration.EnumName #>).GetFields().Where(x => x.IsStatic && x.IsPublic && x.FieldType == typeof(<#= Configuration.EnumName #>))
.Select(x => x.GetValue(null)).OfType<<#= Configuration.EnumName #>>().ToList();
}
return _list;
}
public static List<<#= Configuration.EnumName #>> Values()
{
return ToList();
}
/// <summary>
/// Returns the enum value based on the matching Name of the enum. Case-insensitive search.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static <#= Configuration.EnumName #> ValueOf(string key)
{
return ToList().FirstOrDefault(x => string.Compare(x.Name, key, true) == 0);
}
//---------------------------------------------------------------------------------------------------
// I N S T A N C E _ D E F I N I T I O N
//---------------------------------------------------------------------------------------------------
public string Name { get; private set; }
public string Description { get; private set; }
public override string ToString() { return this.Name; }
/// <summary>
/// Implcitly converts to string.
/// </summary>
/// <param name="d"></param>
public static implicit operator string(<#= Configuration.EnumName #> d)
{
return d.ToString();
}
/// <summary>
/// Compares based on the == method. Handles nulls gracefully.
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static bool operator !=(<#= Configuration.EnumName #> a, <#= Configuration.EnumName #> b)
{
return !(a == b);
}
/// <summary>
/// Compares based on the .Equals method. Handles nulls gracefully.
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static bool operator ==(<#= Configuration.EnumName #> a, <#= Configuration.EnumName #> b)
{
return a?.ToString() == b?.ToString();
}
/// <summary>
/// Compares based on the .ToString() method
/// </summary>
/// <param name="o"></param>
/// <returns></returns>
public override bool Equals(object o)
{
return this.ToString() == o?.ToString();
}
/// <summary>
/// Compares based on the .ToString() method
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public bool Equals(<#= Configuration.EnumName #> other)
{
return this.ToString() == other?.ToString();
}
/// <summary>
/// Compares based on the .Name property
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return this.Name.GetHashCode();
}
}
}
<#+
public static class Helpers
{
public static string PrintEnumProperties(object nodes)
{
string o = "";
Type nodesTp = Configuration.Nodes.GetType();
PropertyInfo[] props = nodesTp.GetProperties().OrderBy(p => p.Name).ToArray();
for(int i = 0; i < props.Length; i++)
{
var prop = props[i];
if (Configuration.IncludeComments)
{
o += "\r\n\r\n";
o += "\r\n ///<summary>";
o += "\r\n /// "+Helpers.PrintPropertyValue(prop, Configuration.Nodes);
o += "\r\n ///</summary>";
}
o += "\r\n public static readonly "+Configuration.EnumName+" "+prop.Name+ " = new "+Configuration.EnumName+"(){ Name = \""+prop.Name+"\", Description = "+Helpers.PrintPropertyValue(prop, Configuration.Nodes)+ "};";
}
o += "\r\n\r\n";
return o;
}
private static Dictionary<string, string> GetValuesMap()
{
Type nodesTp = Configuration.Nodes.GetType();
PropertyInfo[] props= nodesTp.GetProperties();
var dic = new Dictionary<string,string>();
for(int i = 0; i < props.Length; i++)
{
var prop = nodesTp.GetProperties()[i];
dic[prop.Name] = prop.GetValue(Configuration.Nodes).ToString();
}
return dic;
}
public static string PrintMasterValuesMap(object nodes)
{
Type nodesTp = Configuration.Nodes.GetType();
PropertyInfo[] props= nodesTp.GetProperties();
string o = " private static readonly Dictionary<string, string> ValuesMap = new Dictionary<string, string>()\r\n {";
for(int i = 0; i < props.Length; i++)
{
var prop = nodesTp.GetProperties()[i];
o += "\r\n { \""+prop.Name+"\", "+(Helpers.PrintPropertyValue(prop,Configuration.Nodes)+" },");
}
o += ("\r\n };\r\n");
return o;
}
public static string PrintPropertyValue(PropertyInfo prop, object objInstance)
{
switch(prop.PropertyType.ToString()){
case "System.Double":
return prop.GetValue(objInstance).ToString()+"D";
case "System.Float":
return prop.GetValue(objInstance).ToString()+"F";
case "System.Decimal":
return prop.GetValue(objInstance).ToString()+"M";
case "System.Long":
return prop.GetValue(objInstance).ToString()+"L";
case "System.Boolean":
case "System.Int16":
case "System.Int32":
return prop.GetValue(objInstance).ToString().ToLowerInvariant();
case "System.String":
return "\""+prop.GetValue(objInstance)+"\"";
}
return prop.GetValue(objInstance).ToString();
}
public static string _ (int numSpaces)
{
string o = "";
for(int i = 0; i < numSpaces; i++){
o += " ";
}
return o;
}
}
#>
Finally, you recompile your Enum.tt file and the output looks like this:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Linq;
using System.Collections.Generic;
namespace YourName.Space
{
public class ResponseStatusCode
{
//---------------------------------------------------------------------------------------------------
// V A L U E S _ L I S T
//---------------------------------------------------------------------------------------------------
///<summary>
/// "The response was successful."
///</summary>
public static readonly ResponseStatusCode SUCCESS = new ResponseStatusCode(){ Name = "SUCCESS", Description = "The response was successful."};
///<summary>
/// "The request was not successful."
///</summary>
public static readonly ResponseStatusCode NON_SUCCESS = new ResponseStatusCode(){ Name = "NON_SUCCESS", Description = "The request was not successful."};
///<summary>
/// "The resource requested has been discontinued and can no longer be accessed."
///</summary>
public static readonly ResponseStatusCode RESOURCE_IS_DISCONTINUED = new ResponseStatusCode(){ Name = "RESOURCE_IS_DISCONTINUED", Description = "The resource requested has been discontinued and can no longer be accessed."};
private static List<ResponseStatusCode> _list { get; set; } = null;
public static List<ResponseStatusCode> ToList()
{
if (_list == null)
{
_list = typeof(ResponseStatusCode).GetFields().Where(x => x.IsStatic && x.IsPublic && x.FieldType == typeof(ResponseStatusCode))
.Select(x => x.GetValue(null)).OfType<ResponseStatusCode>().ToList();
}
return _list;
}
public static List<ResponseStatusCode> Values()
{
return ToList();
}
/// <summary>
/// Returns the enum value based on the matching Name of the enum. Case-insensitive search.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static ResponseStatusCode ValueOf(string key)
{
return ToList().FirstOrDefault(x => string.Compare(x.Name, key, true) == 0);
}
//---------------------------------------------------------------------------------------------------
// I N S T A N C E _ D E F I N I T I O N
//---------------------------------------------------------------------------------------------------
public string Name { get; set; }
public string Description { get; set; }
public override string ToString() { return this.Name; }
/// <summary>
/// Implcitly converts to string.
/// </summary>
/// <param name="d"></param>
public static implicit operator string(ResponseStatusCode d)
{
return d.ToString();
}
/// <summary>
/// Compares based on the == method. Handles nulls gracefully.
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static bool operator !=(ResponseStatusCode a, ResponseStatusCode b)
{
return !(a == b);
}
/// <summary>
/// Compares based on the .Equals method. Handles nulls gracefully.
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static bool operator ==(ResponseStatusCode a, ResponseStatusCode b)
{
return a?.ToString() == b?.ToString();
}
/// <summary>
/// Compares based on the .ToString() method
/// </summary>
/// <param name="o"></param>
/// <returns></returns>
public override bool Equals(object o)
{
return this.ToString() == o?.ToString();
}
/// <summary>
/// Compares based on the .Name property
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return this.Name.GetHashCode();
}
}
}

Categories

Resources