Class Coin has the following properties: MoneyType, Value, Diameter.
MoneyType is enum:
enum CoinType
{
Cent,
Nickel,
Dime,
QuarterDollar,
HalfDollar,
Dollar,
}
Each MoneyType should have specific Value and Diameter, for example Cent: Value = 1 and Diameter = 19, so if I assign MoneyType, Value and Diameter should be assigned automatically according to MoneyType. Not sure how to do this. Maybe some kind of enum tuples?
For example:
enum CoinType
{
(Cent, 1, 19),
(Nickel, 10, 21),
.....
}
I just want that every MoneyType has specific Value and Diameter.
Another way you can do it is by implementing your custom enum.
Source is modified according to your needs.
#region Base Abstract Class
public abstract class EnumBaseType<T> where T : EnumBaseType<T>
{
protected static List<T> enumValues = new List<T>();
public readonly string Key;
public readonly int Value;
public readonly int Diameter;
public EnumBaseType(string key, int value, int diameter)
{
Key = key;
Value = value;
Diameter = diameter;
enumValues.Add((T)this);
}
protected static System.Collections.ObjectModel.ReadOnlyCollection<T> GetBaseValues()
{
return enumValues.AsReadOnly();
}
protected static T GetBaseByKey(string key)
{
foreach (T t in enumValues)
{
if (t.Key == key) return t;
}
return null;
}
}
#endregion
#region Enhanced Enum Sample
public class MoneyType : EnumBaseType<MoneyType>
{
public static readonly MoneyType Cent = new MoneyType("Cent", 1, 19);
public static readonly MoneyType Nickel = new MoneyType("Nickel", 5, 25);
public static readonly MoneyType Dime = new MoneyType("Dime", 10, 30);
public static readonly MoneyType QuarterDollar = new MoneyType("QuarterDollar", 25, 15);
public static readonly MoneyType HalfDollar = new MoneyType("HalfDollar", 50, 100);
public static readonly MoneyType Dollar = new MoneyType("Dollar", 100, 29);
public MoneyType(string key, int value, int diameter)
: base(key, value, diameter)
{
}
public static ReadOnlyCollection<MoneyType> GetValues()
{
return GetBaseValues();
}
public static MoneyType GetByKey(string key)
{
return GetBaseByKey(key);
}
}
#endregion
public class Test
{
public Test()
{
foreach (MoneyType rating in MoneyType.GetValues())
{
Console.Out.WriteLine("Key:{0} Value:{1}", rating.Key, rating.Value);
if (rating == MoneyType.Dollar)
{
Console.Out.WriteLine("This is a dollar!");
}
}
foreach (MoneyType rating in MoneyType.GetValues())
{
if (rating.Diameter == MoneyType.Nickel.Diameter)
{
Console.Out.WriteLine("This is a Nickel diameter!");
}
}
}
}
source
EDIT:
Just found this: Type-safe-enum pattern
An enum is nothing more than an INT value with a name. It stores only one discrete value. What you want to use is a class.
UPDATE:
Sorry, about my mistake. It's actually been quite awhile since I've used C#. To make it up I've written out what I mean:
enum CoinType {
Cent=1,
Nickel=5,
Dime=10,
QuarterDollar=25,
HalfDollar=50,
Dollar=100,
}
class Coin {
public CoinType type;
public int Diameter {
get {
switch (type) {
case CoinType.Cent: return 19;
case CoinType.Nickel: return 25;
case CoinType.Dime: return 20;
case CoinType.QuarterDollar: return 40;
case CoinType.HalfDollar: return 40;
case CoinType.Dollar: return 40;
}
return 0;
}
}
}
You can add custom attributes onto the enum members.
enum CoinType
{
[Value=1]
[Diameter=19]
Cent,
...
}
You can then use reflection to get the info from the attributes.
You just need a mapping from CoinType to diameter and another from CoinType to value. Both can be done with a simple switch statement.
enum CoinType
{
Cent,
Nickel,
Dime,
QuarterDollar,
HalfDollar,
Dollar,
}
static class CoinTypeExts
{
static double Diameter(this CoinType coinType)
{
switch (coinType)
{
case Cent: return 19;
etc...
}
}
static double Value(this CoinType coinType)
{
switch (coinType)
{
case CoinType.Cent: return 1.0;
etc...
}
}
}
We all know, that in C# an ENUM Type cannot defined with numbers (integers)
e.g. public enum SOME_INTEGERS {3,6,8,11} is not possible
So my question is, how can I define such a resticted type of integers (set of some selected integers) in C#?
In other words, I want to define a variable like this:
private SOME_INTEGERS myVariable;
myVariable may only have the values 3,6,8 or 11
You can use something like this:
public enum SOME_INTEGERS {
One = 1,
Three = 3,
Five = 5
}
SOME_INTEGERS integer = SOME_INTEGERS.Three;
Console.WriteLine((int)integer);//3
Here are some options:
// note that ((SomeIntegers)1) is a valid value with this scheme
public enum SomeIntegers { Three = 3, Six = 6, Eight = 8, Eleven = 11 }
// this stores the set of integers, but your logic to ensure the variable is
// one of these values must exist elsewhere, e.g. in property getters/setters
public ISet<int> SomeIntegers = new HashSet<int> {3,6,8,11};
// this class is a pseudo-enum, and with the exception of reflection,
// will ensure that only the specified values can be set
public sealed class SomeIntegers
{
public static readonly SomeIntegers Three = new SomeIntegers(3);
public static readonly SomeIntegers Six = new SomeIntegers(6);
public static readonly SomeIntegers Eight = new SomeIntegers(8);
public static readonly SomeIntegers Eleven = new SomeIntegers(11);
public int Value { get; private set; }
private SomeIntegers(int value)
{
this.Value = value;
}
public static implicit operator int(SomeIntegers someInteger)
{
return someInteger.Value;
}
public static explicit operator SomeIntegers(int value)
{
switch (value)
{
case 3:
return Three;
case 6:
return Six;
case 8:
return Eight;
case 11:
return Eleven;
default:
throw new ArgumentException("Invalid value", "value");
}
}
public override string ToString()
{
return this.Value.ToString();
}
}
Maybe a struct:
struct MyInt
{
static readonly int[] legalValues = { 3, 6, 8, 11 };
public int Value
{
get;
private set;
}
public bool IsIllegal
{
get
{
return Value == 0;
}
}
MyInt(int value)
: this()
{
Value = value;
}
public static implicit operator MyInt(int value)
{
if (legalValues.Contains(value))
{
return new MyInt(value);
}
return new MyInt();
}
}
But you can create illegal values.
I have a List<Unit> where Unit contains Name and Value. In this object I store information about apparel sizes Name contains size names (S,M,L,XL..) and Value contains the quantity of that size.
This unit list is contained from a database, but the list comes in random order, so in the liste it might be like this:
Unit(M,3)
Unit(S,1)
Unit(XXL,2)
Unit(L,2)
I would like to sort the list so that it become more like this:
Unit(S,1)
Unit(M,3)
Unit(L,2)
Unit(XXLL,2)
I cant order on the string ASCE or DESC since it M comes before S and so on.
Then I thought I might create an reference Array with the correct order (XXS,XS,S,M,L,XL,XXL,XXXL), but how can I sort my list according to the reference.
Or are there other clever ways of doing this?
Update
Thanks for all good answers, I landed on the Enum solution, and it finally looks like this:
public class Unit
{
public Unit()
{
}
public Unit(string name, int value)
{
Value = value;
SizeCode = AssignSizeCode(name);
}
public SizeCode SizeCode { get; set; }
public int Value { get; set; }
private SizeCode AssignSizeCode(string name)
{
switch (name)
{
case "XXS":
return SizeCode.XXS;
case "XS":
return SizeCode.XS;
case "S":
return SizeCode.S;
case "M":
return SizeCode.M;
case "L":
return SizeCode.L;
case "XL":
return SizeCode.XL;
case "XXL":
return SizeCode.XXL;
case "XXXL":
return SizeCode.XXXL;
default:
return SizeCode.Unknown;
}
}
}
public enum SizeCode
{
XXS = 1,
XS = 2,
S = 3,
M = 4,
L = 5,
XL = 6,
XXL = 7,
XXXL = 8,
Unknown = 9
}
And I sort it like this:
units = units.OrderBy(x => (int)x.SizeCode).ToList();
Any comments, or things I can improve?
How about using a enum
public enum Size
{
Small = 1,
Medium = 2,
// etc
}
Then you can convert the enum value in Unit class to int and sort by the integer value.
Ok, I consider you should have OrderIndex column in your database and sort by that column.
the dirty way is to have your own class with interface : IComparer or do the same as delegate for sorting.
Check ICompararer in MSDN: http://msdn.microsoft.com/en-us/library/system.collections.icomparer.aspx
You can do exactly what MSDN suggest here:
// First, declare a few classes that implement the IComparer interface.
public class CompareShirtSize : IComparer<string>
{
// Because the class implements IComparer, it must define a
// Compare method. The method returns a signed integer that indicates
// whether s1 > s2 (return is greater than 0), s1 < s2 (return is negative),
// or s1 equals s2 (return value is 0). This Compare method compares strings.
public int Compare(string size1, string size2)
{
// Do size comarison here
return ConvertSizeToInt(size1) - ConvertSizeToInt(size2);
}
private int ConvertSizeToInt(string size)
{
switch (size)
{
case "XXS":
return 1;
case "XS":
return 2;
case "S":
return 3;
case "M":
return 4;
case "L":
return 5;
default:
// some error handling
}
}
// The following method tests the Compare methods defined in the previous classes.
public static void OrderByIComparer()
{
List<Unit> units;
// Sort the elements of the array alphabetically.
var sortedList = units.OrderBy(unit => unit.Size, new CompareShirtSize ());
}
You could add a Size property of type int in your class Unit. Then sort your list using this Size property.
public class Unit1
{
public Unit1(string name)
{
this.Name = name;
switch (this.Name)
{
case "XXS":
this.Size = 1;
break;
case "XS":
this.Size = 2;
break;
case "S":
this.Size = 3;
break;
case "M":
this.Size = 4;
break;
case "L":
this.Size = 5;
break;
}
}
public string Name { get; set; }
public int Size { get; private set; }
public int Value { get; set; }
}
private static void Main(string[] args)
{
List<Unit1> list1 = new List<Unit1>();
list1.Add(new Unit1("XS") { Value = 1 });
list1.Add(new Unit1("M") { Value = 1 });
list1.Add(new Unit1("S") { Value = 1 });
list1.Add(new Unit1("L") { Value = 1 });
var sortedList = list1.OrderBy(z => z.Size).ToList();
}
You simply need to use a Comparison Delegate. Firstly, make a function that just assigns a number to every size and then use that for comparison:
(I am not sure whether your sizes are stored as a String as an enum; but I would recommend storing them as an enum with the ordinal numbers in order of the sizes, increasing or decreasing. This will help make your comparison delegate faster and simpler).
public class ShirtSizeCompare {
private static int getIndex(Unit x) {
if(x == Null) { return -1; }
if(x.size == "S") {
return 0;
} else if(x.size == "M") {
return 1;
}
///...
}
private static int CompareShirts(Unit x, Unit y) {
int _x = getIndex(x);
int _y = getIndex(y);
if(_x < _y) {
return -1;
} else if(_x == _y) {
return 0;
} else {
return 1;
}
}
}
Then, simply use the Comparison delegate to sort the list:
List<Unit> unitList;
unitList.sort(CompareShirts);
The comparison delegate basically takes as input two variables x and y and returns:
<0 (if x < y)
>0 (if x > y)
0 (if x == y)
Check this page for more information: http://msdn.microsoft.com/en-us/library/w56d4y5z.aspx
I want a user to input "Sun" and have that represent "1".
Console.Write("Enter a Day: ");
day = Console.ReadLine();
can enum do this?
Yes.
enum Days { Sun = 1, /*...*/ }
string day = Console.ReadLine();
Days d = (Days)Enum.Parse(typeof(Days), day);
Yes - you can use Enum.Parse (and Enum.TryParse as of .NET 4) to parse a string to an enum value:
Day day = (Day) Enum.Parse(typeof(Day), "Sun");
or
Day day;
if (Enum.TryParse<Day>("Sun", out day))
{
// Success!
}
It's still somewhat ugly, mind you - there's a certain amount of casting involved in the first call, and the second wouldn't stop you from trying to parse to any value type.
The final reason I don't really like Parse/TryParse is that they will parse string representations of the numeric values of the enums - so "1" would successfully parse, even though it's clearly not the name of an enum value. That seems a bit clunky to me.
There's a nicer (IMO!) approach if you use Unconstrained Melody, a small open source project I wrote to allow generics with enum constraints. Then you'd have:
Day day = Enums.ParseName<Day>("Sun");
or
Day day;
if (Enums.TryParseName<Day>("Sun", out day))
{
// Success!
}
No casting, and you can't accidentally use it on a non-enum type. (There are various other goodies in the project, of course... description parsing etc.)
If you have an enum, lets say:
enum SkyObjects
{
Sun = 1,
Star = 2
}
You can then have the following:
SkyObjects day = Enum.Parse(typeof(SkyObjects ), Console.ReadLine());
This will have Sun, represented as 1 as you like.
or,... another candidate for an immutable value type struct that "appears as" and "behaves" like an enumeration, but has additional fuinctionality as required by your domain model concerns... Using the type defined below you can write
var myDay = (InPutDay)"Sunday";
or, ...
int x = (int)InPutDay.Sun;
or,
int x = (int) InputDay.Parse("Sunday");
Use this type:
public struct InPutDay
{
private int val;
private bool isDef;
private InPutDay( ) { } // private to prevent direct instantiation
private InPutDay(int value) { id=value; isDef = true; }
public bool HasValue { get { return isDef; } }
public bool isNull{ get { return !isDef; } }
public static InPutDay Null = new InPutDay();
public static InPutDay Sun = new InPutDay(1);
public static InPutDay Mon = new InPutDay(2);
public static InPutDay Tue = new InPutDay(3);
public static InPutDay Wed = new InPutDay(4);
public static InPutDay Thu = new InPutDay(5);
public static InPutDay Fri = new InPutDay(6);
public static InPutDay Sat = new InPutDay(7);
public static InPutDay Parse(string s)
{
switch (s.ToUpper().Substring(0,3))
{
case "SUN": return InPutDay.Sun;
case "MON": return InPutDay.Mon;
case "TUE": return InPutDay.Tue;
case "WED": return InPutDay.Wed;
case "THU": return InPutDay.Thu;
case "FRI": return InPutDay.Fri;
case "SAT": return InPutDay.Sat;
default return InPutDay.Null;
}
}
public static implicit operator int(InPutDay inDay)
{ return val; }
public static explicit operator InPutDay (int inDay)
{
if (inDay > 0 && inDay < 8)
return new InPutDay(inDay);
// either throw exception ....
throw new ArgumentException(
"InPutDay integer values must be between 1 and 7.");
// or return null instance
return InPutDay.Null;
}
public static explicit operator InPutDay (string inDayName)
{ return InPutDay.Parse(inDayName); }
}
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>();