Custom C# Enum ToString() when generated dynamically - c#

I generate dynamic enums that represent integer IDs from my database in a C# ASP.NET solution. I would like two things, although neither may be possible.
1) I want the .ToString() method to give me "345" for example, not the string name of the enum (the int it represents as a string). Every answer to this question seems to be adding
[Description="Blah"]
EnumName = 1
above the declaration and using a GetDescription() method. I have no idea how to do this with the dynamic code that I am using.
2) I'd rather not cast to an int to use it as such, I'd rather (Enum.Name == 5) for example. If this isn't possible I'll cast, but I really don't want to use ((int)Enum.Name)).ToString();
Here's the dynamic code generation:
public static void Main()
{
AppDomain domain = AppDomain.CurrentDomain;
AssemblyName aName = new AssemblyName("DynamicEnums");
AssemblyBuilder ab = domain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Save);
ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");
List<Type> types = new List<Type>();
foreach(ReferenceType rt in GetTypes())
{
EnumBuilder eb = mb.DefineEnum(rt.Name, TypeAttributes.Public, typeof(int));
foreach (Reference r in GetReferences(rt.ID))
{
eb.DefineLiteral(NameFix(r.Name), r.ID);
}
types.Add(eb.CreateType());
}
ab.Save(aName.Name + ".dll");
foreach (Type t in types)
{
foreach (object o in Enum.GetValues(t))
{
Console.WriteLine("{0}.{1} = {2}", t, o, ((int) o));
}
Console.WriteLine();
//Console.ReadKey();
}
Console.WriteLine();
Console.WriteLine("Dynamic Enums Built Successfully.");
}
public static string NameFix(string name)
{
//Strip all non alphanumeric characters
string r = Regex.Replace(name, #"[^\w]", "");
//Enums cannot begin with a number
if (Regex.IsMatch(r, #"^\d"))
r = "N" + r;
return r;
}
There may just be no way to do what I want to do, and I'll be stuck using:
(int)Countries.USA //For int value
((int)Countries.CAN).ToString() //For string representation of int value, ex. "354"
Any ideas?

Could you adapt the type-safe enum pattern to do what you need?
public class MyEnum
{
#region Enum Values
// Pre defined values.
public static readonly MyEnum ValueOne = new MyEnum(0);
public static readonly MyEnum ValueTwo = new MyEnum(1);
// All values in existence.
private static readonly Dictionary<int, MyEnum> existingEnums = new Dictionary<int, MyEnum>{{ValueOne.Value, ValueOne}, {ValueTwo.Value, ValueTwo}};
#endregion
#region Enum Functionality
private readonly int Value;
private MyEnum(int value)
{
Value = value;
}
public static MyEnum GetEnum(int value)
{
// You will probably want to make this thread-safe.
if (!existingEnums.ContainsKey(value)) existingEnums[value] = new MyEnum(value);
return existingEnums[value];
}
public override string ToString()
{
return Value.ToString();
}
#endregion
}
Usage:
private void Foo(MyEnum enumVal)
{
return "Enum Value: " + enumVal; // returns "Enum Value: (integer here)
}
Or:
MyEnum.GetValue(2) == MyEnum.GetValue(4); // false
MyEnum.GetValue(3) == MyEnum.GetValue(3); // true

So you actually want to convert the Enum value to a string not the name? Casting to the Enum's underlying type is the simplest way to get the value out. I think you will struggle to get anything shorter or simpler than ((int)...).
If you don't want to "enumerate" some values, or want to do somthing different you could make your own class of YourEnum which basically has the cast built in, casting when required seems easier and more readable.
Perhaps you actually want some constants.
const string Blah = "345";
EDIT
I had another idea, you could write an extension method for Enum like this,
public static class MyExtentions
{
public static string ValueString(this Enum e)
{
var ut = Enum.GetUnderlyingType(e.GetType());
var castToString = typeOf(MyExtentions).GetMethod("CastToString");
var gcast = cast.MakeGenericMethod(ut);
var gparams = new object[] {e};
return gcast.Invoke(null, gparams).ToString();
}
public static string CastToString<T>(object o)
{
return ((T)o).ToString();
}
}
With this you can call ValueString() on any Enum instance and get a string of the value. It clearly used reflection so the performance won't be amazing but I don't think that matters in your case.

As you're using the Enum class type, how about using the Enum.Format method.
For example:
enum EnumClassA {One, Two, Three, Four};
...
EnumClassA chosenValue = EnumClassA.Three;
Console.WriteLine("Chosen value is {0}", Enum.Format(typeof(EnumClassA), chosenValue, "d"));
This should give an output of:
Chosen value is 2
edit
Another option would be:
EnumClassA.Three.ToString("d"); //Enum.Name.ToString("d")
This also gives a string value of "2".
** edit **
As you're doing comparisons to see if the value exists within your enums how about using Enum.IsDefined(enumType, value) which returns a bool?
Console.WriteLine("Does the enumClassA contain {0} result is {1}", 5, Enum.IsDefined(typeof(enumClassA), 5));
This gives an output of:
Does the enumClassA contain 5 result is False

I realise that the question has been marked as answered, but perhaps using an extension might be useful?
It still allows you to use your generated enums this way.
ps. Take care when calling GetString - don't accidentally call ToString instead!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;
namespace ConsoleApplication1
{
public enum YourEnum
{
Apples = 1,
Pears = 2,
}
class Program
{
static void Main(string[] args)
{
foreach (var value in (YourEnum[])Enum.GetValues(typeof(YourEnum)))
{
int v = value.GetValue();
Console.WriteLine("{0} = {1} (int)", value.ToString(), v);
string s = value.GetString();
Console.WriteLine("{0} = {1} (string)", value.ToString(), s);
}
Console.ReadLine();
//Results:
//Apples = 1 (int)
//Apples = 1 (string)
//Pears = 2 (int)
//Pears = 2 (string)
}
}
public static class EnumExtensions
{
public static int GetValue(this Enum value)
{
return Convert.ToInt32(value);
}
public static string GetString(this Enum value)
{
return Convert.ToInt32(value).ToString();
}
}
}

Related

What is the efficient way to store and read additional information from enums

I was trying to store and retrieve additional information from enums. I ended up with 2 methods for it.
The first method is by using custom attributes.
https://stackoverflow.com/a/22054994/5078531
https://stackoverflow.com/a/35040378/5078531
public class DayAttribute : Attribute
{
public string Name { get; private set; }
public DayAttribute(string name)
{
this.Name = name;
}
}
enum Days
{
[Day("Saturday")]
Sat,
[Day("Sunday")]
Sun
}
public static TAttribute GetAttribute<TAttribute>(this Enum value)
where TAttribute : Attribute
{
var enumType = value.GetType();
var name = Enum.GetName(enumType, value);
return enumType.GetField(name).GetCustomAttributes(false).OfType<TAttribute>().SingleOrDefault();
}
The second method I found here, by writing an extension method on enums.
https://stackoverflow.com/a/680515/5078531
public enum ArrowDirection
{
North,
South,
East,
West
}
public static class ArrowDirectionExtensions
{
public static UnitVector UnitVector(this ArrowDirection self)
{
switch(self)
{
case ArrowDirection.North:
return new UnitVector(0, 1);
case ArrowDirection.South:
return new UnitVector(0, -1);
case ArrowDirection.East:
return new UnitVector(1, 0);
case ArrowDirection.West:
return new UnitVector(-1, 0);
default:
return null;
}
}
}
If am looking for the performance which method should I choose ? or is there any other efficient methods which am missing?
Both are valid ways of implementing it; as are many other ways. Personally, I like the convenience of the first. The performance penalty of reflection can be mitigated by processing the attributes once only, and storing (presumably in a static field) - potentially as a flat array if the enum values are contiguous and 0-based; otherwise, perhaps in a dictionary.
You can make DayaAttributeCache more generic if you like such that it can store other enum and attribute types. I just did this quick to show a caching approach. Enum values have to be continuous starting at 0 but this can be changed to handle that case if needed.
public static class DaysAttributeCache
{
private static readonly string[] Cache;
static DaysAttributeCache()
{
Type enumType = typeof(Days);
Cache = new string[Enum.GetValues(enumType).Length];
foreach (Enum value in Enum.GetValues(enumType))
{
var name = Days.GetName(enumType, value);
DayAttribute attribute = enumType
.GetField(name)
.GetCustomAttributes(false)
.OfType<DayAttribute>()
.SingleOrDefault();
string weekDay = attribute?.Name;
Cache[((IConvertible)value).ToInt32(CultureInfo.InvariantCulture)] = weekDay;
}
}
public static string GetWeekday(this Days value)
{
return Cache[(int)value];
}
}
Called like this...
string saturday = Days.Sat.GetWeekday();

How to define an enum with string value?

I am trying to define an Enum and add valid common separators which used in CSV or similar files. Then I am going to bind it to a ComboBox as a data source so whenever I add or remove from the Enum definition, I would not need to change anything in the combo box.
The problem is how can I define enum with string representation, something like:
public enum SeparatorChars{Comma = ",", Tab = "\t", Space = " "}
You can't - enum values have to be integral values. You can either use attributes to associate a string value with each enum value, or in this case if every separator is a single character you could just use the char value:
enum Separator
{
Comma = ',',
Tab = '\t',
Space = ' '
}
(EDIT: Just to clarify, you can't make char the underlying type of the enum, but you can use char constants to assign the integral value corresponding to each enum value. The underlying type of the above enum is int.)
Then an extension method if you need one:
public string ToSeparatorString(this Separator separator)
{
// TODO: validation
return ((char) separator).ToString();
}
You can achieve it but it will require a bit of work.
Define an attribute class which will contain the string value for enum.
Define an extension method which will return back the value from the attribute. Eg..GetStringValue(this Enum value) will return attribute value.
Then you can define the enum like this..
public enum Test : int {
[StringValue("a")]
Foo = 1,
[StringValue("b")]
Something = 2
}
To get back the value from Attribute Test.Foo.GetStringValue();
Refer : Enum With String Values In C#
As far as I know, you will not be allowed to assign string values to enum. What you can do is create a class with string constants in it.
public static class SeparatorChars
{
public static String Comma { get { return ",";} }
public static String Tab { get { return "\t,";} }
public static String Space { get { return " ";} }
}
For a simple enum of string values (or any other type):
public static class MyEnumClass
{
public const string
MyValue1 = "My value 1",
MyValue2 = "My value 2";
}
Usage: string MyValue = MyEnumClass.MyValue1;
Maybe it's too late, but here it goes.
We can use the attribute EnumMember to manage Enum values.
public enum UnitOfMeasure
{
[EnumMember(Value = "KM")]
Kilometer,
[EnumMember(Value = "MI")]
Miles
}
This way the result value for UnitOfMeasure will be KM or MI. This also can be seen in Andrew Whitaker answer.
You can't do this with enums, but you can do it like that:
public static class SeparatorChars
{
public static string Comma = ",";
public static string Tab = "\t";
public static string Space = " ";
}
A class that emulates enum behaviour but using string instead of int can be created as follows...
public class GrainType
{
private string _typeKeyWord;
private GrainType(string typeKeyWord)
{
_typeKeyWord = typeKeyWord;
}
public override string ToString()
{
return _typeKeyWord;
}
public static GrainType Wheat = new GrainType("GT_WHEAT");
public static GrainType Corn = new GrainType("GT_CORN");
public static GrainType Rice = new GrainType("GT_RICE");
public static GrainType Barley = new GrainType("GT_BARLEY");
}
Usage...
GrainType myGrain = GrainType.Wheat;
PrintGrainKeyword(myGrain);
then...
public void PrintGrainKeyword(GrainType grain)
{
Console.Writeline("My Grain code is " + grain.ToString()); // Displays "My Grain code is GT_WHEAT"
}
It is kind of late for answer, but maybe it helps someone in future. I found it easier to use struct for this kind of problem.
Following sample is copy pasted part from MS code:
namespace System.IdentityModel.Tokens.Jwt
{
//
// Summary:
// List of registered claims from different sources http://tools.ietf.org/html/rfc7519#section-4
// http://openid.net/specs/openid-connect-core-1_0.html#IDToken
public struct JwtRegisteredClaimNames
{
//
// Summary:
// http://tools.ietf.org/html/rfc7519#section-4
public const string Actort = "actort";
//
// Summary:
// http://tools.ietf.org/html/rfc7519#section-4
public const string Typ = "typ";
//
// Summary:
// http://tools.ietf.org/html/rfc7519#section-4
public const string Sub = "sub";
//
// Summary:
// http://openid.net/specs/openid-connect-frontchannel-1_0.html#OPLogout
public const string Sid = "sid";
//
// Summary:
// http://tools.ietf.org/html/rfc7519#section-4
public const string Prn = "prn";
//
// Summary:
// http://tools.ietf.org/html/rfc7519#section-4
public const string Nbf = "nbf";
//
// Summary:
// http://tools.ietf.org/html/rfc7519#section-4
public const string Nonce = "nonce";
//
// Summary:
// http://tools.ietf.org/html/rfc7519#section-4
public const string NameId = "nameid";
}
}
You can't, because enum can only be based on a primitive numeric type.
You could try using a Dictionary instead:
Dictionary<String, char> separators = new Dictionary<string, char>
{
{"Comma", ','},
{"Tab", '\t'},
{"Space", ' '},
};
Alternatively, you could use a Dictionary<Separator, char> or Dictionary<Separator, string> where Separator is a normal enum:
enum Separator
{
Comma,
Tab,
Space
}
which would be a bit more pleasant than handling the strings directly.
For people arriving here looking for an answer to a more generic question, you can extend the static class concept if you want your code to look like an enum.
The following approach works when you haven't finalised the enum names you want and the enum values are the string representation of the enam name; use nameof() to make your refactoring simpler.
public static class Colours
{
public static string Red => nameof(Red);
public static string Green => nameof(Green);
public static string Blue => nameof(Blue);
}
This achieves the intention of an enum that has string values (such as the following pseudocode):
public enum Colours
{
"Red",
"Green",
"Blue"
}
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.
Usage:
///<completionlist cref="HexColor"/>
class HexColor : StringEnum<HexColor>
{
public static readonly HexColor Blue = New("#FF0000");
public static readonly HexColor Green = New("#00FF00");
public static readonly HexColor Red = New("#000FF");
}
Features
Your StringEnum looks somewhat similar to a regular enum:
// 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)
Intellisense will suggest the enum name if the class is annotated with the xml comment <completitionlist>. (Works in both C# and VB): i.e.
Instalation
Either:
Install latest 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.
Or paste the following StringEnum base class to your project. (latest version)
public abstract class StringEnum<T> : IEquatable<T> where T : StringEnum<T>, new()
{
protected string Value;
private static IList<T> valueList = new List<T>();
protected static T New(string value)
{
if (value == null)
return null; // the null-valued instance is null.
var result = new T() { Value = value };
valueList.Add(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 sensitivity.</param>
public static T Parse(string value, bool caseSensitive = false)
{
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 sensitivity.</param>
public static T TryParse(string value, bool caseSensitive = false)
{
if (value == null) return null;
if (valueList.Count == 0) System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(T).TypeHandle); // force static fields initialization
var field = valueList.FirstOrDefault(f => f.Value.Equals(value,
caseSensitive ? StringComparison.Ordinal
: StringComparison.OrdinalIgnoreCase));
// Not using InvariantCulture because it's only supported in NETStandard >= 2.0
if (field == null)
return null;
return field;
}
}
For Newtonsoft.Json serialization support, copy this extended version instead. StringEnum.cs
I realized after the fact that this code is similar to Ben's answer. I sincerely wrote it from scratch. However I think it has a few extras, like the <completitionlist> hack, the resulting class looks more like an Enum, no use of reflection on Parse(), the NuGet package and repo where I will hopefully address incoming issues and feedback.
Building on some of the answers here I have implemented a reusable base class that mimics the behaviour of an enum but with string as the underlying type. It supports various operations including:
getting a list of possible values
converting to string
comparison with other instances via .Equals, ==, and !=
conversion to/from JSON using a JSON.NET JsonConverter
This is the base class in it's entirety:
public abstract class StringEnumBase<T> : IEquatable<T>
where T : StringEnumBase<T>
{
public string Value { get; }
protected StringEnumBase(string value) => this.Value = value;
public override string ToString() => this.Value;
public static List<T> AsList()
{
return typeof(T)
.GetProperties(BindingFlags.Public | BindingFlags.Static)
.Where(p => p.PropertyType == typeof(T))
.Select(p => (T)p.GetValue(null))
.ToList();
}
public static T Parse(string value)
{
List<T> all = AsList();
if (!all.Any(a => a.Value == value))
throw new InvalidOperationException($"\"{value}\" is not a valid value for the type {typeof(T).Name}");
return all.Single(a => a.Value == value);
}
public bool Equals(T other)
{
if (other == null) return false;
return this.Value == other?.Value;
}
public override bool Equals(object obj)
{
if (obj == null) return false;
if (obj is T other) return this.Equals(other);
return false;
}
public override int GetHashCode() => this.Value.GetHashCode();
public static bool operator ==(StringEnumBase<T> a, StringEnumBase<T> b) => a?.Equals(b) ?? false;
public static bool operator !=(StringEnumBase<T> a, StringEnumBase<T> b) => !(a?.Equals(b) ?? false);
public class JsonConverter<T> : Newtonsoft.Json.JsonConverter
where T : StringEnumBase<T>
{
public override bool CanRead => true;
public override bool CanWrite => true;
public override bool CanConvert(Type objectType) => ImplementsGeneric(objectType, typeof(StringEnumBase<>));
private static bool ImplementsGeneric(Type type, Type generic)
{
while (type != null)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == generic)
return true;
type = type.BaseType;
}
return false;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken item = JToken.Load(reader);
string value = item.Value<string>();
return StringEnumBase<T>.Parse(value);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is StringEnumBase<T> v)
JToken.FromObject(v.Value).WriteTo(writer);
}
}
}
And this is how you would implement your "string enum":
[JsonConverter(typeof(JsonConverter<Colour>))]
public class Colour : StringEnumBase<Colour>
{
private Colour(string value) : base(value) { }
public static Colour Red => new Colour("red");
public static Colour Green => new Colour("green");
public static Colour Blue => new Colour("blue");
}
Which could be used like this:
public class Foo
{
public Colour colour { get; }
public Foo(Colour colour) => this.colour = colour;
public bool Bar()
{
if (this.colour == Colour.Red || this.colour == Colour.Blue)
return true;
else
return false;
}
}
I hope someone finds this useful!
What I have recently begun doing is using Tuples
public static (string Fox, string Rabbit, string Horse) Animals = ("Fox", "Rabbit", "Horse");
...
public static (string Comma, string Tab, string Space) SeparatorChars = (",", "\t", " ");
I wish there were a more elegant solution, like just allowing string type enum in the language level, but it seems that it is not supported yet. The code below is basically the same idea as other answers, but I think it is shorter and it can be reused. All you have to do is adding a [Description("")] above each enum entry and add a class that has 10 lines.
The class:
public static class Extensions
{
public static string ToStringValue(this Enum en)
{
var type = en.GetType();
var memInfo = type.GetMember(en.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
var stringValue = ((DescriptionAttribute)attributes[0]).Description;
return stringValue;
}
}
Usage:
enum Country
{
[Description("Deutschland")]
Germany,
[Description("Nippon")]
Japan,
[Description("Italia")]
Italy,
}
static void Main(string[] args)
{
Show(new[] {Country.Germany, Country.Japan, Country.Italy});
void Show(Country[] countries)
{
foreach (var country in countries)
{
Debug.WriteLine(country.ToStringValue());
}
}
}
Well first you try to assign strings not chars, even if they are just one character. use ',' instead of ",". Next thing is, enums only take integral types without char you could use the unicode value, but i would strongly advice you not to do so.
If you are certain that these values stay the same, in differnt cultures and languages, i would use a static class with const strings.
While it is really not possible to use a char or a string as the base for an enum, i think this is not what you really like to do.
Like you mentioned you'd like to have an enum of possibilities and show a string representation of this within a combo box. If the user selects one of these string representations you'd like to get out the corresponding enum. And this is possible:
First we have to link some string to an enum value. This can be done by using the DescriptionAttribute like it is described here or here.
Now you need to create a list of enum values and corresponding descriptions. This can be done by using the following method:
/// <summary>
/// Creates an List with all keys and values of a given Enum class
/// </summary>
/// <typeparam name="T">Must be derived from class Enum!</typeparam>
/// <returns>A list of KeyValuePair<Enum, string> with all available
/// names and values of the given Enum.</returns>
public static IList<KeyValuePair<T, string>> ToList<T>() where T : struct
{
var type = typeof(T);
if (!type.IsEnum)
{
throw new ArgumentException("T must be an enum");
}
return (IList<KeyValuePair<T, string>>)
Enum.GetValues(type)
.OfType<T>()
.Select(e =>
{
var asEnum = (Enum)Convert.ChangeType(e, typeof(Enum));
return new KeyValuePair<T, string>(e, asEnum.Description());
})
.ToArray();
}
Now you'll have a list of key value pairs of all enums and their description. So let's simply assign this as a data source for a combo box.
var comboBox = new ComboBox();
comboBox.ValueMember = "Key"
comboBox.DisplayMember = "Value";
comboBox.DataSource = EnumUtilities.ToList<Separator>();
comboBox.SelectedIndexChanged += (sender, e) =>
{
var selectedEnum = (Separator)comboBox.SelectedValue;
MessageBox.Show(selectedEnum.ToString());
}
The user sees all the string representations of the enum and within your code you'll get the desired enum value.
Adding still something more as some of the answers here are missing the point of using enums. Naturally one option is is to have well defined strings as static variables etc, but then you're opening your interface for illegal values also, i.e. you need to validate the input. With enums it's guaranteed that only allowed values are passed to your interface.
enum Separator
{
Comma,
Tab,
Space,
CRLF,
SoFunny
}
In addition to this you can use e.g. an internal Dictionary for the mapping purposes.
private readonly Dictionary<Separator, string> separatorMap = new Dictionary<Separator, string>()
{
{ Separator.Comma, "," },
{ Separator.Tab, "\t" },
{ Separator.Space, " " },
{ Separator.CRLF, "\r\n" },
{ Separator.SoFunny, "Your Mom" }
};
Even more sophisticated method for doing this is to create a static class to give the enum new capabilities and handle the mapping there.
Example of using code above would be like.
public string TransformToSingleString(List<string> values, Separator separator)
{
var separateWith = separatorMap[separator];
...
}
Enumaration Class
public sealed class GenericDateTimeFormatType
{
public static readonly GenericDateTimeFormatType Format1 = new GenericDateTimeFormatType("dd-MM-YYYY");
public static readonly GenericDateTimeFormatType Format2 = new GenericDateTimeFormatType("dd-MMM-YYYY");
private GenericDateTimeFormatType(string Format)
{
_Value = Format;
}
public string _Value { get; private set; }
}
Enumaration Consuption
public static void Main()
{
Country A = new Country();
A.DefaultDateFormat = GenericDateTimeFormatType.Format1;
Console.ReadLine();
}
We can't define enumeration as string type. The approved types for an enum are byte, sbyte, short, ushort, int, uint, long, or ulong.
If you need more details on enumeration please follow below link,that link will help you to understand enumeration.
Enumeration
#narendras1414
It works for me..
public class ShapeTypes
{
private ShapeTypes() { }
public static string OVAL
{
get
{
return "ov";
}
private set { }
}
public static string SQUARE
{
get
{
return "sq";
}
private set { }
}
public static string RECTANGLE
{
get
{
return "rec";
}
private set { }
}
}

more elegant design about enum

I'm on learning for C#.
I heared C# is one of the most constructible language. so would you guys make my code more elegant and efficient?
public class ISO639
{
public enum ISO639Code
{
Afrikaans, //af
Albanian, //sq
Amharic, //am
...
Yiddish, //yi
Unknown
}
public static string GetISO639CodeString(ISO639.ISO639Code l)
{
switch (l)
{
case ISO639Code.English: return "en";
case ISO639Code.Japanese: return "ja";
...
case ISO639Code.Hebrew: return "he";
default: return "";
}
public static ISO639.ISO639Code GetISO39CodeValue(string s)
{
switch (s)
{
case "ko" : return ISO639Code.Korean;
case "en" : return ISO639Code.English;
...
case "hu" : return ISO639Code.Hungarian;
default: return ISO639Code.Unknown;
}
}
}
Here is a my class ISO639. This class provides enum for ISO639 code, but I need a type conversion on from ISO639 enum to plain string. (ex. ISO639.ISO639Code.Italian => "it"). I also need a type conversion from plain string to ISO639 enum. (ex. "it" => ISO639.ISO639Code.Italian).
Is there a more efficient coding style for that?
You can add standard System.ComponentModel.Description attribute to each enum entry and then read it.
public enum ISO639Code
{
[Description("af")]
Afrikaans
}
public static class EnumExtensions
{
// Extension method to read Description value
public static string GetDescription(this Enum currentEnum)
{
var fi = currentEnum.GetType().GetField(currentEnum.ToString());
var da = (DescriptionAttribute)Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
return da != null ? da.Description : currentEnum.ToString();
}
}
// **How-to read it**
ISO639Code isoCode = ISO639Code.Afrikaans;
// this will returns "af"
string isoDescription = isoCode.GetDescription();
EDIT:
string searchFor = "af";
ISO639Code foundEntry;
// Loop through all entries descriptions
var allEntries = Enum.GetValues(typeof(ISO639Code));
foreach (var entry in allEntries)
{
// If you will extract this as separate method and use it for search not only loop
// through the all entries - you can put here is yield return description
var currentEntry = ((ISO639Code)entry);
string description = currentEntry.GetDescription();
if (description == searchFor)
{
foundEntry = currentEntry;
break;
}
}
Sure. You can use attributes:
public enum ISO639Code
{
[CodeString("af")] Afrikaans,
[CodeString("sq")] Albanian,
}
Use dictionary, for example: new Dictionary<ISO639Code, string>.
I suggest you to use C# extension methods to enums, they allow you to add whatever logic you want.
For example, see http://pietschsoft.com/post/2008/07/c-enhance-enums-using-extension-methods.aspx
I'd simply store the information in a dictionary-like object. This way you can reference the name by key and get the value directly.
You have an enum:
public enum ISO639Code
{
Afrikaans = 1,
Albanian = 2,
Amharic = 3,
etc.
Create a database table:
ISO639Id int PK,
ISO639Code char(2)
Where the ISO639Id maps to the value of the enum.
In code you'd want a ISO630 Class containing Id and Code values read from the database.
(You can load this once and then cache it in memory.)
The beauty of this approach, is it can be easily extended so that if in future you wanted to store more pieces of information for each ISO639 code, you could simply add another field.
Look at System.Globailzation namespace. The functionality you require looks to be already implemented there. At worst you can see the architecture and technique applied in the .Net framework to solve a very similar problem.
Enumerations are really good to work in code, as they are really strongly typed and make refactoring easier.
Follow these steps:
Use attributes for whatever extra information you want to attach to an enum. Usually this is a simple Description attribute. Something like:
public enum IsoCodes
{
[Description("af")]
Africans = 0,
[Description("am")]
Americans = 1
}
Then write some extension methods to convert strings and integers to and from this enum:
public static string GetDescription(this Enum value)
{
var entries = value.ToString().Split(FlagEnumSeparatorCharacter);
var description = new string[entries.Length];
for (var i = 0; i < entries.Length; i++)
{
var fieldInfo = value.GetType().GetField(entries[i].Trim());
var attributes = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[];
description[i] = (attributes.Length > 0) ? attributes[0].Description : entries[i].Trim();
}
return String.Join(", ", description);
}
public static int GetValue(this Enum value)
{
return (int)value.GetType().GetField(value.ToString()).GetRawConstantValue();
}
public static T ToEnum<T>(this string value)
{
if (typeof(T).BaseType.Name != typeof(Enum).Name)
{
throw new Exception("Not an enum");
}
return (T)Enum.Parse(typeof(T), value, true);
}
public static T ToEnum<T>(this int value)
{
if (typeof(T).BaseType.Name != typeof(Enum).Name)
{
throw new Exception("Not an enum");
}
return (T)Enum.ToObject(typeof(T), value);
}
Now use your enums as you like.
I would go with having ISO639Code as class instead of enum:
public class ISO639Code
{
public string Value { get; set ; }
public string Code { get; set; }
public ISO639Code()
{
this.Value = "";
this.Code = "";
}
public ISO639Code(string value, string code)
: this()
{
this.Value = value;
this.Code = code;
}
public override bool Equals(object obj)
{
if (obj != null)
{
if (obj is string)
return obj.ToString().Equals(this.Value, StringComparison.CurrentCultureIgnoreCase);
if (obj is ISO639Code)
return ((ISO639Code)obj).Value.Equals(this.Value, StringComparison.CurrentCultureIgnoreCase);
}
return false;
}
public override int GetHashCode()
{
return this.Value.GetHashCode();
}
public override string ToString()
{
return this.Value;
}
}
Then have global List<ISO639Code> with all possible codes, and to find specific code based on code name or value, just search for this in the List.
Personally, I prefer this over tweaking the enum.

Possible to have strings for enums?

I want to have an enum as in:
enum FilterType
{
Rigid = "Rigid",
SoftGlow = "Soft / Glow",
Ghost = "Ghost",
}
How to achieve this? Is there a better way to do this? It's gonna be used for an instance of an object where it's gonna be serialized/deserialized. It's also gonna populate a dropdownlist.
using System.ComponentModel;
enum FilterType
{
[Description("Rigid")]
Rigid,
[Description("Soft / Glow")]
SoftGlow,
[Description("Ghost")]
Ghost ,
}
You can get the value out like this
public static String GetEnumerationDescription(Enum e)
{
Type type = e.GetType();
FieldInfo fieldInfo = type.GetField(e.ToString());
DescriptionAttribute[] da = (DescriptionAttribute[])(fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false));
if (da.Length > 0)
{
return da[0].Description;
}
return e.ToString();
}
No, but if you want to scope "const" strings and use them like an enum, here's what I do:
public static class FilterType
{
public const string Rigid = "Rigid";
public const string SoftGlow = "Soft / Glow";
public const string Ghost ="Ghost";
}
If you're comfortable with extension methods, you can easily do what you're after:
//Can return string constants, the results of a Database call,
//or anything else you need to do to get the correct value
//(for localization, for example)
public static string EnumValue(this MyEnum e) {
switch (e) {
case MyEnum.First:
return "First Friendly Value";
case MyEnum.Second:
return "Second Friendly Value";
case MyEnum.Third:
return "Third Friendly Value";
}
return "Horrible Failure!!";
}
This way you can do:
Private MyEnum value = MyEnum.First;
Console.WriteLine(value.EnumValue());
No, but you can cheat like this:
public enum FilterType{
Rigid,
SoftGlow,
Ghost
}
And then when you need their string values you can just do FilterType.Rigid.ToString().
Enums are always linked to an integer value. So no.
You can do FilterType.Rigid.ToString() to obtain the string value although it can't be localized directly.
You can get the Enum name as a string like this
FilterType myType = FilterType.Rigid;
String strType = myType.ToString();
However, you may be stuck with the Camel Case/Hungarian notation, but you can easily convert that to a more user friendly String using a method like this (Not the prettiest solution, I would be grateful for input on optimizing this):
Public Shared Function NormalizeCamelCase(ByVal str As String) As String
If String.IsNullOrEmpty(str) Then
Return String.Empty
End If
Dim i As Integer = 0
Dim upperCount As Integer = 0
Dim otherCount As Integer = 0
Dim normalizedString As String = str
While i < normalizedString.Length
If Char.IsUpper(normalizedString, i) Then
''Current char is Upper Case
upperCount += 1
If i > 0 AndAlso Not normalizedString(i - 1).Equals(" "c) Then
''Current char is not first and preceding char is not a space
''...insert a space, move to next char
normalizedString = normalizedString.Insert(i, " ")
i += 1
End If
ElseIf Not Char.IsLetter(normalizedString, i) Then
otherCount += 1
End If
''Move to next char
i += 1
End While
If upperCount + otherCount = str.Length Then
''String is in all caps, return original string
Return str
Else
Return normalizedString
End If
End Function
If that's still not pretty enough, you may want to look into Custom Attributes, which can be retrieved using Reflection...
In the System.ComponentModel namespace there is a class DescriptionAttribute that works well here.
enum FilterType
{
Rigid,
[Description("Soft / Glow")]
SoftGlow,
Ghost,
}
Then to get the description and fail over to the ToString()
var descriptionAttribute = Value.GetType()
.GetField(Value.ToString())
.GetCustomAttributes(typeof(DescriptionAttribute), false)
.OfType <DescriptionAttribute>()
.FirstOrDefault()??new DescriptionAttribute(Value.ToString());
This is not possible. C# only allows integral enum types (int, short, long, etc.). You can either create a lightweight "enum-like" class or use static constants.
static class FilterTypes
{
public const string Rigid = "Rigid";
// ...
}
// or ...
class FilterType
{
static readonly FilterType RigidFilterType = new FilterType("Rigid");
string name;
FilterType(string name) // private constructor
{
this.name = name;
}
public static FilterType Rigid
{
get { return FilterType.RigidFilterType; }
}
// ...
}
It is not outright possible. However you can fake it using an array.
First, Create you enum the way you would a regular one:
public enum Regexs
{
ALPHA = 0,
NUMERIC = 1,
etc..
}
Then you create an array that holds the values corresponding to the enum values:
private static string[] regexs = new string[]
{
"[A-Za-z]",
"[0-9]",
"etc"...
}
Then you can access your strings through the enum value:
public void runit(Regexs myregexEnum)
{
Regex regex = new Regex( regexs [(int)myregexEnum] );
}
No, it's not possible.
The approved types for an enum are
byte, sbyte, short, ushort, int, uint,
long, or ulong.
However, you can retrieve the declared name of an enum with the Enum class:
string name = Enum.GetName(typeof(FilterType), FilterType.Rigid);
If this doesn't work for you, a collection of string constants collected in a class might.
You can use an Attribute over the values
[System.ComponentModel.Description("Rigid")]
example:
enum FilterType
{
[System.ComponentModel.Description("Rigid")]
Rigid,
[System.ComponentModel.Description("Soft / Glow")]
SoftGlow,
[System.ComponentModel.Description("Ghost")]
Ghost
}
and use Reflection to get the descriptions.
Enum extension method:
public static string GetDescription(this Enum en)
{
var type = en.GetType();
var memInfo = type.GetMember(en.ToString());
if (memInfo != null && memInfo.Length > 0)
{
var attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attrs != null && attrs.Length > 0)
return ((DescriptionAttribute)attrs[0]).Description;
}
return en.ToString();
}
use it:
FilterType = FilterType.Rigid;
string description= result.GetDescription();
Along the lines of Shaun Bowe's example you can also do this in C# 3 with an extension method for enum (I did not come up with and cannot, for the life of me, remember where I did).
Create an Attribute:
public class DisplayTextAttribute : Attribute {
public DisplayTextAttribute(String text) {
Text = text;
}
public string Text { get; set; }
}
Create an extension:
public static class EnumHelpers {
public static string GetDisplayText(this Enum enumValue) {
var type = enumValue.GetType();
MemberInfo[] memberInfo = type.GetMember(enumValue.ToString());
if (memberInfo == null || memberInfo.Length == 0)
return enumValue.ToString();
object[] attributes = memberInfo[0].GetCustomAttributes(typeof(DisplayTextAttribute), false);
if (attributes == null || attributes.Length == 0)
return enumValue.ToString();
return ((DisplayTextAttribute)attributes[0]).Text;
}
}
I've found this to be really tidy solution.
In your enum add the following:
enum FilterType{
Rigid,
[DisplayText("Soft / Glow")]
SoftGlow,
Ghost
}
You could then access FilterType.GetDisplayText() which will pull back the string for the unattributed enums and the displayText for the ones with attributes.

How do I cast int to enum in C#?

How do I cast an int to an enum in C#?
From an int:
YourEnum foo = (YourEnum)yourInt;
From a string:
YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString);
// The foo.ToString().Contains(",") check is necessary for
// enumerations marked with a [Flags] attribute.
if (!Enum.IsDefined(typeof(YourEnum), foo) && !foo.ToString().Contains(","))
{
throw new InvalidOperationException(
$"{yourString} is not an underlying value of the YourEnum enumeration."
);
}
From a number:
YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum), yourInt);
Just cast it:
MyEnum e = (MyEnum)3;
Check if it's in range using Enum.IsDefined:
if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }
Alternatively, use an extension method instead of a one-liner:
public static T ToEnum<T>(this string enumString)
{
return (T) Enum.Parse(typeof (T), enumString);
}
Usage:
Color colorEnum = "Red".ToEnum<Color>();
OR
string color = "Red";
var colorEnum = color.ToEnum<Color>();
I think to get a complete answer, people have to know how enums work internally in .NET.
How stuff works
An enum in .NET is a structure that maps a set of values (fields) to a basic type (the default is int). However, you can actually choose the integral type that your enum maps to:
public enum Foo : short
In this case the enum is mapped to the short data type, which means it will be stored in memory as a short and will behave as a short when you cast and use it.
If you look at it from a IL point of view, a (normal, int) enum looks like this:
.class public auto ansi serializable sealed BarFlag extends System.Enum
{
.custom instance void System.FlagsAttribute::.ctor()
.custom instance void ComVisibleAttribute::.ctor(bool) = { bool(true) }
.field public static literal valuetype BarFlag AllFlags = int32(0x3fff)
.field public static literal valuetype BarFlag Foo1 = int32(1)
.field public static literal valuetype BarFlag Foo2 = int32(0x2000)
// and so on for all flags or enum values
.field public specialname rtspecialname int32 value__
}
What should get your attention here is that the value__ is stored separately from the enum values. In the case of the enum Foo above, the type of value__ is int16. This basically means that you can store whatever you want in an enum, as long as the types match.
At this point I'd like to point out that System.Enum is a value type, which basically means that BarFlag will take up 4 bytes in memory and Foo will take up 2 -- e.g. the size of the underlying type (it's actually more complicated than that, but hey...).
The answer
So, if you have an integer that you want to map to an enum, the runtime only has to do 2 things: copy the 4 bytes and name it something else (the name of the enum). Copying is implicit because the data is stored as value type - this basically means that if you use unmanaged code, you can simply interchange enums and integers without copying data.
To make it safe, I think it's a best practice to know that the underlying types are the same or implicitly convertible and to ensure the enum values exist (they aren't checked by default!).
To see how this works, try the following code:
public enum MyEnum : int
{
Foo = 1,
Bar = 2,
Mek = 5
}
static void Main(string[] args)
{
var e1 = (MyEnum)5;
var e2 = (MyEnum)6;
Console.WriteLine("{0} {1}", e1, e2);
Console.ReadLine();
}
Note that casting to e2 also works! From the compiler perspective above this makes sense: the value__ field is simply filled with either 5 or 6 and when Console.WriteLine calls ToString(), the name of e1 is resolved while the name of e2 is not.
If that's not what you intended, use Enum.IsDefined(typeof(MyEnum), 6) to check if the value you are casting maps to a defined enum.
Also note that I'm explicit about the underlying type of the enum, even though the compiler actually checks this. I'm doing this to ensure I don't run into any surprises down the road. To see these surprises in action, you can use the following code (actually I've seen this happen a lot in database code):
public enum MyEnum : short
{
Mek = 5
}
static void Main(string[] args)
{
var e1 = (MyEnum)32769; // will not compile, out of bounds for a short
object o = 5;
var e2 = (MyEnum)o; // will throw at runtime, because o is of type int
Console.WriteLine("{0} {1}", e1, e2);
Console.ReadLine();
}
Take the following example:
int one = 1;
MyEnum e = (MyEnum)one;
I am using this piece of code to cast int to my enum:
if (typeof(YourEnum).IsEnumDefined(valueToCast)) return (YourEnum)valueToCast;
else { //handle it here, if its not defined }
I find it the best solution.
Below is a nice utility class for Enums
public static class EnumHelper
{
public static int[] ToIntArray<T>(T[] value)
{
int[] result = new int[value.Length];
for (int i = 0; i < value.Length; i++)
result[i] = Convert.ToInt32(value[i]);
return result;
}
public static T[] FromIntArray<T>(int[] value)
{
T[] result = new T[value.Length];
for (int i = 0; i < value.Length; i++)
result[i] = (T)Enum.ToObject(typeof(T),value[i]);
return result;
}
internal static T Parse<T>(string value, T defaultValue)
{
if (Enum.IsDefined(typeof(T), value))
return (T) Enum.Parse(typeof (T), value);
int num;
if(int.TryParse(value,out num))
{
if (Enum.IsDefined(typeof(T), num))
return (T)Enum.ToObject(typeof(T), num);
}
return defaultValue;
}
}
For numeric values, this is safer as it will return an object no matter what:
public static class EnumEx
{
static public bool TryConvert<T>(int value, out T result)
{
result = default(T);
bool success = Enum.IsDefined(typeof(T), value);
if (success)
{
result = (T)Enum.ToObject(typeof(T), value);
}
return success;
}
}
If you're ready for the 4.0 .NET Framework, there's a new Enum.TryParse() function that's very useful and plays well with the [Flags] attribute. See Enum.TryParse Method (String, TEnum%)
Sometimes you have an object to the MyEnum type. Like
var MyEnumType = typeof(MyEnum);
Then:
Enum.ToObject(typeof(MyEnum), 3)
If you have an integer that acts as a bitmask and could represent one or more values in a [Flags] enumeration, you can use this code to parse the individual flag values into a list:
for (var flagIterator = 0; flagIterator < 32; flagIterator++)
{
// Determine the bit value (1,2,4,...,Int32.MinValue)
int bitValue = 1 << flagIterator;
// Check to see if the current flag exists in the bit mask
if ((intValue & bitValue) != 0)
{
// If the current flag exists in the enumeration, then we can add that value to the list
// if the enumeration has that flag defined
if (Enum.IsDefined(typeof(MyEnum), bitValue))
Console.WriteLine((MyEnum)bitValue);
}
}
Note that this assumes that the underlying type of the enum is a signed 32-bit integer. If it were a different numerical type, you'd have to change the hardcoded 32 to reflect the bits in that type (or programatically derive it using Enum.GetUnderlyingType())
This is an flags enumeration aware safe convert method:
public static bool TryConvertToEnum<T>(this int instance, out T result)
where T: Enum
{
var enumType = typeof (T);
var success = Enum.IsDefined(enumType, instance);
if (success)
{
result = (T)Enum.ToObject(enumType, instance);
}
else
{
result = default(T);
}
return success;
}
To convert a string to ENUM or int to ENUM constant we need to use Enum.Parse function. Here is a youtube video https://www.youtube.com/watch?v=4nhx4VwdRDk which actually demonstrate's with string and the same applies for int.
The code goes as shown below where "red" is the string and "MyColors" is the color ENUM which has the color constants.
MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");
Slightly getting away from the original question, but I found an answer to Stack Overflow question Get int value from enum useful. Create a static class with public const int properties, allowing you to easily collect together a bunch of related int constants, and then not have to cast them to int when using them.
public static class Question
{
public static readonly int Role = 2;
public static readonly int ProjectFunding = 3;
public static readonly int TotalEmployee = 4;
public static readonly int NumberOfServers = 5;
public static readonly int TopBusinessConcern = 6;
}
Obviously, some of the enum type functionality will be lost, but for storing a bunch of database id constants, it seems like a pretty tidy solution.
The following is a slightly better extension method:
public static string ToEnumString<TEnum>(this int enumValue)
{
var enumString = enumValue.ToString();
if (Enum.IsDefined(typeof(TEnum), enumValue))
{
enumString = ((TEnum) Enum.ToObject(typeof (TEnum), enumValue)).ToString();
}
return enumString;
}
This parses integers or strings to a target enum with partial matching in .NET 4.0 using generics like in Tawani's utility class. I am using it to convert command-line switch variables which may be incomplete. Since an enum cannot be null, you should logically provide a default value. It can be called like this:
var result = EnumParser<MyEnum>.Parse(valueToParse, MyEnum.FirstValue);
Here's the code:
using System;
public class EnumParser<T> where T : struct
{
public static T Parse(int toParse, T defaultVal)
{
return Parse(toParse + "", defaultVal);
}
public static T Parse(string toParse, T defaultVal)
{
T enumVal = defaultVal;
if (defaultVal is Enum && !String.IsNullOrEmpty(toParse))
{
int index;
if (int.TryParse(toParse, out index))
{
Enum.TryParse(index + "", out enumVal);
}
else
{
if (!Enum.TryParse<T>(toParse + "", true, out enumVal))
{
MatchPartialName(toParse, ref enumVal);
}
}
}
return enumVal;
}
public static void MatchPartialName(string toParse, ref T enumVal)
{
foreach (string member in enumVal.GetType().GetEnumNames())
{
if (member.ToLower().Contains(toParse.ToLower()))
{
if (Enum.TryParse<T>(member + "", out enumVal))
{
break;
}
}
}
}
}
FYI: The question was about integers, which nobody mentioned will also explicitly convert in Enum.TryParse()
From a string: (Enum.Parse is out of Date, use Enum.TryParse)
enum Importance
{}
Importance importance;
if (Enum.TryParse(value, out importance))
{
}
You should build in some type matching relaxation to be more robust.
public static T ToEnum<T>(dynamic value)
{
if (value == null)
{
// default value of an enum is the object that corresponds to
// the default value of its underlying type
// https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-table
value = Activator.CreateInstance(Enum.GetUnderlyingType(typeof(T)));
}
else if (value is string name)
{
return (T)Enum.Parse(typeof(T), name);
}
return (T)Enum.ToObject(typeof(T),
Convert.ChangeType(value, Enum.GetUnderlyingType(typeof(T))));
}
Test Case
[Flags]
public enum A : uint
{
None = 0,
X = 1 < 0,
Y = 1 < 1
}
static void Main(string[] args)
{
var value = EnumHelper.ToEnum<A>(7m);
var x = value.HasFlag(A.X); // true
var y = value.HasFlag(A.Y); // true
var value2 = EnumHelper.ToEnum<A>("X");
var value3 = EnumHelper.ToEnum<A>(null);
Console.ReadKey();
}
Here's an extension method that casts Int32 to Enum.
It honors bitwise flags even when the value is higher than the maximum possible. For example if you have an enum with possibilities 1, 2, and 4, but the int is 9, it understands that as 1 in absence of an 8. This lets you make data updates ahead of code updates.
public static TEnum ToEnum<TEnum>(this int val) where TEnum : struct, IComparable, IFormattable, IConvertible
{
if (!typeof(TEnum).IsEnum)
{
return default(TEnum);
}
if (Enum.IsDefined(typeof(TEnum), val))
{//if a straightforward single value, return that
return (TEnum)Enum.ToObject(typeof(TEnum), val);
}
var candidates = Enum
.GetValues(typeof(TEnum))
.Cast<int>()
.ToList();
var isBitwise = candidates
.Select((n, i) => {
if (i < 2) return n == 0 || n == 1;
return n / 2 == candidates[i - 1];
})
.All(y => y);
var maxPossible = candidates.Sum();
if (
Enum.TryParse(val.ToString(), out TEnum asEnum)
&& (val <= maxPossible || !isBitwise)
){//if it can be parsed as a bitwise enum with multiple flags,
//or is not bitwise, return the result of TryParse
return asEnum;
}
//If the value is higher than all possible combinations,
//remove the high imaginary values not accounted for in the enum
var excess = Enumerable
.Range(0, 32)
.Select(n => (int)Math.Pow(2, n))
.Where(n => n <= val && n > 0 && !candidates.Contains(n))
.Sum();
return Enum.TryParse((val - excess).ToString(), out asEnum) ? asEnum : default(TEnum);
}
The easy and clear way for casting an int to enum in C#:
public class Program
{
public enum Color : int
{
Blue = 0,
Black = 1,
Green = 2,
Gray = 3,
Yellow = 4
}
public static void Main(string[] args)
{
// From string
Console.WriteLine((Color) Enum.Parse(typeof(Color), "Green"));
// From int
Console.WriteLine((Color)2);
// From number you can also
Console.WriteLine((Color)Enum.ToObject(typeof(Color), 2));
}
}
For string, you can do the following:
var result = Enum.TryParse(typeof(MyEnum), yourString, out yourEnum)
And make sure to check the result to determine if the conversion failed.
For int, you can do the following:
MyEnum someValue = (MyEnum)myIntValue;
In my case, I needed to return the enum from a WCF service. I also needed a friendly name, not just the enum.ToString().
Here's my WCF Class.
[DataContract]
public class EnumMember
{
[DataMember]
public string Description { get; set; }
[DataMember]
public int Value { get; set; }
public static List<EnumMember> ConvertToList<T>()
{
Type type = typeof(T);
if (!type.IsEnum)
{
throw new ArgumentException("T must be of type enumeration.");
}
var members = new List<EnumMember>();
foreach (string item in System.Enum.GetNames(type))
{
var enumType = System.Enum.Parse(type, item);
members.Add(
new EnumMember() { Description = enumType.GetDescriptionValue(), Value = ((IConvertible)enumType).ToInt32(null) });
}
return members;
}
}
Here's the Extension method that gets the Description from the Enum.
public static string GetDescriptionValue<T>(this T source)
{
FieldInfo fileInfo = source.GetType().GetField(source.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fileInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes != null && attributes.Length > 0)
{
return attributes[0].Description;
}
else
{
return source.ToString();
}
}
Implementation:
return EnumMember.ConvertToList<YourType>();
It can help you to convert any input data to user desired enum. Suppose you have an enum like below which by default int. Please add a Default value at first of your enum. Which is used at helpers medthod when there is no match found with input value.
public enum FriendType
{
Default,
Audio,
Video,
Image
}
public static class EnumHelper<T>
{
public static T ConvertToEnum(dynamic value)
{
var result = default(T);
var tempType = 0;
//see Note below
if (value != null &&
int.TryParse(value.ToString(), out tempType) &&
Enum.IsDefined(typeof(T), tempType))
{
result = (T)Enum.ToObject(typeof(T), tempType);
}
return result;
}
}
N.B: Here I try to parse value into int, because enum is by default int
If you define enum like this which is byte type.
public enum MediaType : byte
{
Default,
Audio,
Video,
Image
}
You need to change parsing at helper method from
int.TryParse(value.ToString(), out tempType)
to
byte.TryParse(value.ToString(), out tempType)
I check my method for following inputs
EnumHelper<FriendType>.ConvertToEnum(null);
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("-1");
EnumHelper<FriendType>.ConvertToEnum("6");
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("2");
EnumHelper<FriendType>.ConvertToEnum(-1);
EnumHelper<FriendType>.ConvertToEnum(0);
EnumHelper<FriendType>.ConvertToEnum(1);
EnumHelper<FriendType>.ConvertToEnum(9);
sorry for my english
Different ways to cast to and from Enum
enum orientation : byte
{
north = 1,
south = 2,
east = 3,
west = 4
}
class Program
{
static void Main(string[] args)
{
orientation myDirection = orientation.north;
Console.WriteLine(“myDirection = {0}”, myDirection); //output myDirection =north
Console.WriteLine((byte)myDirection); //output 1
string strDir = Convert.ToString(myDirection);
Console.WriteLine(strDir); //output north
string myString = “north”; //to convert string to Enum
myDirection = (orientation)Enum.Parse(typeof(orientation),myString);
}
}
I don't know anymore where I get the part of this enum extension, but it is from stackoverflow. I am sorry for this! But I took this one and modified it for enums with Flags.
For enums with Flags I did this:
public static class Enum<T> where T : struct
{
private static readonly IEnumerable<T> All = Enum.GetValues(typeof (T)).Cast<T>();
private static readonly Dictionary<int, T> Values = All.ToDictionary(k => Convert.ToInt32(k));
public static T? CastOrNull(int value)
{
T foundValue;
if (Values.TryGetValue(value, out foundValue))
{
return foundValue;
}
// For enums with Flags-Attribut.
try
{
bool isFlag = typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0;
if (isFlag)
{
int existingIntValue = 0;
foreach (T t in Enum.GetValues(typeof(T)))
{
if ((value & Convert.ToInt32(t)) > 0)
{
existingIntValue |= Convert.ToInt32(t);
}
}
if (existingIntValue == 0)
{
return null;
}
return (T)(Enum.Parse(typeof(T), existingIntValue.ToString(), true));
}
}
catch (Exception)
{
return null;
}
return null;
}
}
Example:
[Flags]
public enum PetType
{
None = 0, Dog = 1, Cat = 2, Fish = 4, Bird = 8, Reptile = 16, Other = 32
};
integer values
1=Dog;
13= Dog | Fish | Bird;
96= Other;
128= Null;
You simply use Explicit conversion Cast int to enum or enum to int
class Program
{
static void Main(string[] args)
{
Console.WriteLine((int)Number.three); //Output=3
Console.WriteLine((Number)3);// Outout three
Console.Read();
}
public enum Number
{
Zero = 0,
One = 1,
Two = 2,
three = 3
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace SamplePrograme
{
public class Program
{
public enum Suit : int
{
Spades = 0,
Hearts = 1,
Clubs = 2,
Diamonds = 3
}
public static void Main(string[] args)
{
//from string
Console.WriteLine((Suit) Enum.Parse(typeof(Suit), "Clubs"));
//from int
Console.WriteLine((Suit)1);
//From number you can also
Console.WriteLine((Suit)Enum.ToObject(typeof(Suit) ,1));
}
}
}
I prefer a short way using a nullable enum type variable.
var enumValue = (MyEnum?)enumInt;
if (!enumValue.HasValue)
{
throw new ArgumentException(nameof(enumValue));
}
You just do like below:
int intToCast = 1;
TargetEnum f = (TargetEnum) intToCast ;
To make sure that you only cast the right values ​​and that you can throw an exception otherwise:
int intToCast = 1;
if (Enum.IsDefined(typeof(TargetEnum), intToCast ))
{
TargetEnum target = (TargetEnum)intToCast ;
}
else
{
// Throw your exception.
}
Note that using IsDefined is costly and even more than just casting, so it depends on your implementation to decide to use it or not.
You can use an extension method.
public static class Extensions
{
public static T ToEnum<T>(this string data) where T : struct
{
if (!Enum.TryParse(data, true, out T enumVariable))
{
if (Enum.IsDefined(typeof(T), enumVariable))
{
return enumVariable;
}
}
return default;
}
public static T ToEnum<T>(this int data) where T : struct
{
return (T)Enum.ToObject(typeof(T), data);
}
}
Use it like the below code:
Enum:
public enum DaysOfWeeks
{
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6,
Sunday = 7,
}
Usage:
string Monday = "Mon";
int Wednesday = 3;
var Mon = Monday.ToEnum<DaysOfWeeks>();
var Wed = Wednesday.ToEnum<DaysOfWeeks>();

Categories

Resources