C# enum type-safety - c#

Is there a way to force the C# enum to only accept one of the several explicitly named constants, or is there another feature that does? The C# reference has this afterthought:
It is possible to assign any arbitrary integer value to an enum type.
However, you should not do this because the implicit expectation is
that an enum variable will only hold one of the values defined by the
enum. To assign an arbitrary value to a variable of an enumeration
type is to introduce a high risk for errors.
(A new language was designed that allows this sort of sloppiness. That is baffling to me.)

As far as I know, you can't stop C# from allowing conversions between enums and integers.
As a workaround, you could instead use a custom type with restricted instantiation. The usage will look similar, but you will also have the opportunity to define methods and operators for this type.
Say you have this enum:
enum DayOfWeek
{
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
}
You could use a sealed class in its place. The advantage is that you get comparisons for free (because a value comparison and a reference comparison are equivalent for this case). The disadvantage is that (like all reference types in C#), it's nullable.
sealed class DayOfWeek
{
public static readonly DayOfWeek Monday = new DayOfWeek(0);
public static readonly DayOfWeek Tuesday = new DayOfWeek(1);
public static readonly DayOfWeek Wednesday = new DayOfWeek(2);
public static readonly DayOfWeek Thursday = new DayOfWeek(3);
public static readonly DayOfWeek Friday = new DayOfWeek(4);
public static readonly DayOfWeek Saturday = new DayOfWeek(5);
public static readonly DayOfWeek Sunday = new DayOfWeek(6);
private readonly int _value;
private DayOfWeek(int value)
{
_value = value;
}
}
Or you could use a struct. The advantage is that it's not nullable and thus it's even more similar to an enum. The disadvantage is that you have to implement the comparison code manually:
struct DayOfWeek
{
public static readonly DayOfWeek Monday = new DayOfWeek(0);
public static readonly DayOfWeek Tuesday = new DayOfWeek(1);
public static readonly DayOfWeek Wednesday = new DayOfWeek(2);
public static readonly DayOfWeek Thursday = new DayOfWeek(3);
public static readonly DayOfWeek Friday = new DayOfWeek(4);
public static readonly DayOfWeek Saturday = new DayOfWeek(5);
public static readonly DayOfWeek Sunday = new DayOfWeek(6);
private readonly int _value;
private DayOfWeek(int value)
{
_value = value;
}
public bool Equals(DayOfWeek other)
{
return _value == other._value;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
return obj is DayOfWeek && Equals((DayOfWeek)obj);
}
public override int GetHashCode()
{
return _value;
}
public static bool operator ==(DayOfWeek op1, DayOfWeek op2)
{
return op1.Equals(op2);
}
public static bool operator !=(DayOfWeek op1, DayOfWeek op2)
{
return !(op1 == op2);
}
}

The ability to cast any integer to an enum is mostly because of performance reasons, but an enum implemented as a value type simply can't be protected from containing undefined values. Consider an enum like:
public enum Condition {
Right = 1,
Wrong = 2
}
Even if assignments to an enum variable was restricted to only defined values, you can still create an undefined value by simply putting it in a class:
public class Demo {
public Condition Cond;
}
When you create an instance of the class, the members are initialized to zero, so the Cond member variable would have the undefined value of (Condition)0.
You can make a wrapper class to make sure that an enum value is among the defined values:
public sealed class SafeEnum<T> where T : struct {
public T Value { get; private set; }
public SafeEnum(T value) {
if (!(value is Enum)) {
throw new ArgumentException("The type is not an enumeration.");
}
if (!Enum.IsDefined(typeof(T), value)) {
throw new ArgumentException("The value is not defined in the enumeration.");
}
Value = value;
}
}
Example:
var cond = new SafeEnum<Condition>(Condition.Right); // works
Condition d = cond.Value;
var cond = new SafeEnum<int>(42); // not an enum
var cond = new SafeEnum<Condition>((Condition)42); // not defined
An instance of the class can only contain a value that is defined in the enum, as the constructor won't allow the creation of the instance otherwise.
As the class is immutable, the value can't change to an undefined value.

Related

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

Is it possible to define an implicit conversion of enums in c#?
something that could achieve this?
public enum MyEnum
{
one = 1, two = 2
}
MyEnum number = MyEnum.one;
long i = number;
If not, why not?
There is a solution. Consider the following:
public sealed class AccountStatus
{
public static readonly AccountStatus Open = new AccountStatus(1);
public static readonly AccountStatus Closed = new AccountStatus(2);
public static readonly SortedList<byte, AccountStatus> Values = new SortedList<byte, AccountStatus>();
private readonly byte Value;
private AccountStatus(byte value)
{
this.Value = value;
Values.Add(value, this);
}
public static implicit operator AccountStatus(byte value)
{
return Values[value];
}
public static implicit operator byte(AccountStatus value)
{
return value.Value;
}
}
The above offers implicit conversion:
AccountStatus openedAccount = 1; // Works
byte openedValue = AccountStatus.Open; // Works
This is a fair bit more work than declaring a normal enum (though you can refactor some of the above into a common generic base class). You can go even further by having the base class implement IComparable & IEquatable, as well as adding methods to return the value of DescriptionAttributes, declared names, etc, etc.
I wrote a base class (RichEnum<>) to handle most fo the grunt work, which eases the above declaration of enums down to:
public sealed class AccountStatus : RichEnum<byte, AccountStatus>
{
public static readonly AccountStatus Open = new AccountStatus(1);
public static readonly AccountStatus Closed = new AccountStatus(2);
private AccountStatus(byte value) : base (value)
{
}
public static implicit operator AccountStatus(byte value)
{
return Convert(value);
}
}
The base class (RichEnum) is listed below.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Resources;
namespace Ethica
{
using Reflection;
using Text;
[DebuggerDisplay("{Value} ({Name})")]
public abstract class RichEnum<TValue, TDerived>
: IEquatable<TDerived>,
IComparable<TDerived>,
IComparable, IComparer<TDerived>
where TValue : struct , IComparable<TValue>, IEquatable<TValue>
where TDerived : RichEnum<TValue, TDerived>
{
#region Backing Fields
/// <summary>
/// The value of the enum item
/// </summary>
public readonly TValue Value;
/// <summary>
/// The public field name, determined from reflection
/// </summary>
private string _name;
/// <summary>
/// The DescriptionAttribute, if any, linked to the declaring field
/// </summary>
private DescriptionAttribute _descriptionAttribute;
/// <summary>
/// Reverse lookup to convert values back to local instances
/// </summary>
private static SortedList<TValue, TDerived> _values;
private static bool _isInitialized;
#endregion
#region Constructors
protected RichEnum(TValue value)
{
if (_values == null)
_values = new SortedList<TValue, TDerived>();
this.Value = value;
_values.Add(value, (TDerived)this);
}
#endregion
#region Properties
public string Name
{
get
{
CheckInitialized();
return _name;
}
}
public string Description
{
get
{
CheckInitialized();
if (_descriptionAttribute != null)
return _descriptionAttribute.Description;
return _name;
}
}
#endregion
#region Initialization
private static void CheckInitialized()
{
if (!_isInitialized)
{
ResourceManager _resources = new ResourceManager(typeof(TDerived).Name, typeof(TDerived).Assembly);
var fields = typeof(TDerived)
.GetFields(BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public)
.Where(t => t.FieldType == typeof(TDerived));
foreach (var field in fields)
{
TDerived instance = (TDerived)field.GetValue(null);
instance._name = field.Name;
instance._descriptionAttribute = field.GetAttribute<DescriptionAttribute>();
var displayName = field.Name.ToPhrase();
}
_isInitialized = true;
}
}
#endregion
#region Conversion and Equality
public static TDerived Convert(TValue value)
{
return _values[value];
}
public static bool TryConvert(TValue value, out TDerived result)
{
return _values.TryGetValue(value, out result);
}
public static implicit operator TValue(RichEnum<TValue, TDerived> value)
{
return value.Value;
}
public static implicit operator RichEnum<TValue, TDerived>(TValue value)
{
return _values[value];
}
public static implicit operator TDerived(RichEnum<TValue, TDerived> value)
{
return value;
}
public override string ToString()
{
return _name;
}
#endregion
#region IEquatable<TDerived> Members
public override bool Equals(object obj)
{
if (obj != null)
{
if (obj is TValue)
return Value.Equals((TValue)obj);
if (obj is TDerived)
return Value.Equals(((TDerived)obj).Value);
}
return false;
}
bool IEquatable<TDerived>.Equals(TDerived other)
{
return Value.Equals(other.Value);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
#endregion
#region IComparable Members
int IComparable<TDerived>.CompareTo(TDerived other)
{
return Value.CompareTo(other.Value);
}
int IComparable.CompareTo(object obj)
{
if (obj != null)
{
if (obj is TValue)
return Value.CompareTo((TValue)obj);
if (obj is TDerived)
return Value.CompareTo(((TDerived)obj).Value);
}
return -1;
}
int IComparer<TDerived>.Compare(TDerived x, TDerived y)
{
return (x == null) ? -1 :
(y == null) ? 1 :
x.Value.CompareTo(y.Value);
}
#endregion
public static IEnumerable<TDerived> Values
{
get
{
return _values.Values;
}
}
public static TDerived Parse(string name)
{
foreach (TDerived value in _values.Values)
if (0 == string.Compare(value.Name, name, true) || 0 == string.Compare(value.DisplayName, name, true))
return value;
return null;
}
}
}
You can't do implict conversions (except for zero), and you can't write your own instance methods - however, you can probably write your own extension methods:
public enum MyEnum { A, B, C }
public static class MyEnumExt
{
public static int Value(this MyEnum foo) { return (int)foo; }
static void Main()
{
MyEnum val = MyEnum.A;
int i = val.Value();
}
}
This doesn't give you a lot, though (compared to just doing an explicit cast).
One of the main times I've seen people want this is for doing [Flags] manipulation via generics - i.e. a bool IsFlagSet<T>(T value, T flag); method. Unfortunately, C# 3.0 doesn't support operators on generics, but you can get around this using things like this, which make operators fully available with generics.
struct PseudoEnum
{
public const int
INPT = 0,
CTXT = 1,
OUTP = 2;
};
// ...
var arr = new String[3];
arr[PseudoEnum.CTXT] = "can";
arr[PseudoEnum.INPT] = "use";
arr[PseudoEnum.CTXT] = "as";
arr[PseudoEnum.CTXT] = "array";
arr[PseudoEnum.OUTP] = "index";
I adapted Mark's excellent RichEnum generic baseclass.
Fixing
a number of compilation problems due to missing bits from his libraries (notably: the resource dependent display names weren't completely removed; they are now)
initialization wasn't perfect: if the first thing you did was access the static .Values property from the base class, you'd get a NPE. Fixed this by forcing the base class to curiously-recursively (CRTP) force the static construction of TDerived just in time during CheckInitialized
finally moved CheckInitialized logic into a static constructor (to avoid the penalty of checking each time, the race condition on multithreaded initialization; perhaps this was an impossibility solved by my bullet 1.?)
Kudos to Mark for the splendid idea + implementation, here's to you all:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Resources;
namespace NMatrix
{
[DebuggerDisplay("{Value} ({Name})")]
public abstract class RichEnum<TValue, TDerived>
: IEquatable<TDerived>,
IComparable<TDerived>,
IComparable, IComparer<TDerived>
where TValue : struct, IComparable<TValue>, IEquatable<TValue>
where TDerived : RichEnum<TValue, TDerived>
{
#region Backing Fields
/// <summary>
/// The value of the enum item
/// </summary>
public readonly TValue Value;
/// <summary>
/// The public field name, determined from reflection
/// </summary>
private string _name;
/// <summary>
/// The DescriptionAttribute, if any, linked to the declaring field
/// </summary>
private DescriptionAttribute _descriptionAttribute;
/// <summary>
/// Reverse lookup to convert values back to local instances
/// </summary>
private static readonly SortedList<TValue, TDerived> _values = new SortedList<TValue, TDerived>();
#endregion
#region Constructors
protected RichEnum(TValue value)
{
this.Value = value;
_values.Add(value, (TDerived)this);
}
#endregion
#region Properties
public string Name
{
get
{
return _name;
}
}
public string Description
{
get
{
if (_descriptionAttribute != null)
return _descriptionAttribute.Description;
return _name;
}
}
#endregion
#region Initialization
static RichEnum()
{
var fields = typeof(TDerived)
.GetFields(BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public)
.Where(t => t.FieldType == typeof(TDerived));
foreach (var field in fields)
{
/*var dummy =*/ field.GetValue(null); // forces static initializer to run for TDerived
TDerived instance = (TDerived)field.GetValue(null);
instance._name = field.Name;
instance._descriptionAttribute = field.GetCustomAttributes(true).OfType<DescriptionAttribute>().FirstOrDefault();
}
}
#endregion
#region Conversion and Equality
public static TDerived Convert(TValue value)
{
return _values[value];
}
public static bool TryConvert(TValue value, out TDerived result)
{
return _values.TryGetValue(value, out result);
}
public static implicit operator TValue(RichEnum<TValue, TDerived> value)
{
return value.Value;
}
public static implicit operator RichEnum<TValue, TDerived>(TValue value)
{
return _values[value];
}
public static implicit operator TDerived(RichEnum<TValue, TDerived> value)
{
return value;
}
public override string ToString()
{
return _name;
}
#endregion
#region IEquatable<TDerived> Members
public override bool Equals(object obj)
{
if (obj != null)
{
if (obj is TValue)
return Value.Equals((TValue)obj);
if (obj is TDerived)
return Value.Equals(((TDerived)obj).Value);
}
return false;
}
bool IEquatable<TDerived>.Equals(TDerived other)
{
return Value.Equals(other.Value);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
#endregion
#region IComparable Members
int IComparable<TDerived>.CompareTo(TDerived other)
{
return Value.CompareTo(other.Value);
}
int IComparable.CompareTo(object obj)
{
if (obj != null)
{
if (obj is TValue)
return Value.CompareTo((TValue)obj);
if (obj is TDerived)
return Value.CompareTo(((TDerived)obj).Value);
}
return -1;
}
int IComparer<TDerived>.Compare(TDerived x, TDerived y)
{
return (x == null) ? -1 :
(y == null) ? 1 :
x.Value.CompareTo(y.Value);
}
#endregion
public static IEnumerable<TDerived> Values
{
get
{
return _values.Values;
}
}
public static TDerived Parse(string name)
{
foreach (TDerived value in Values)
if (0 == string.Compare(value.Name, name, true))
return value;
return null;
}
}
}
A sample of usage that I ran on mono:
using System.ComponentModel;
using System;
namespace NMatrix
{
public sealed class MyEnum : RichEnum<int, MyEnum>
{
[Description("aap")] public static readonly MyEnum my_aap = new MyEnum(63000);
[Description("noot")] public static readonly MyEnum my_noot = new MyEnum(63001);
[Description("mies")] public static readonly MyEnum my_mies = new MyEnum(63002);
private MyEnum(int value) : base (value) { }
public static implicit operator MyEnum(int value) { return Convert(value); }
}
public static class Program
{
public static void Main(string[] args)
{
foreach (var enumvalue in MyEnum.Values)
Console.WriteLine("MyEnum {0}: {1} ({2})", (int) enumvalue, enumvalue, enumvalue.Description);
}
}
}
Producing the output
[mono] ~/custom/demo # gmcs test.cs richenum.cs && ./test.exe
MyEnum 63000: my_aap (aap)
MyEnum 63001: my_noot (noot)
MyEnum 63002: my_mies (mies)
Note: mono 2.6.7 requires an extra explicit cast that is not required when using mono 2.8.2...
You cannot declare implicit conversions on enum types, because they can't define methods. The C# implicit keyword compiles into a method starting with 'op_', and it wouldn't work in this case.
You probably could, but not for the enum (you can't add a method to it). You could add an implicit conversion to you own class to allow an enum to be converted to it,
public class MyClass {
public static implicit operator MyClass ( MyEnum input ) {
//...
}
}
MyClass m = MyEnum.One;
The question would be why?
In general .Net avoids (and you should too) any implicit conversion where data can be lost.
enums are largely useless for me because of this, OP.
I end up doing pic-related all the time:
the simple solution
classic example problem is the VirtualKey set for detecting keypresses.
enum VKeys : ushort
{
a = 1,
b = 2,
c = 3
}
// the goal is to index the array using predefined constants
int[] array = new int[500];
var x = array[VKeys.VK_LSHIFT];
problem here is you can't index the array with the enum because it can't implicitly convert enum to ushort (even though we even based the enum on ushort)
in this specific context, enums are obsoleted by the following datastructure
. . . .
public static class VKeys
{
public const ushort
a = 1,
b = 2,
c = 3;
}
I found even easier solution taken from here https://codereview.stackexchange.com/questions/7566/enum-vs-int-wrapper-struct I pasted the code below from that link just in case it does not work in the future.
struct Day
{
readonly int day;
public static readonly Day Monday = 0;
public static readonly Day Tuesday = 1;
public static readonly Day Wednesday = 2;
public static readonly Day Thursday = 3;
public static readonly Day Friday = 4;
public static readonly Day Saturday = 5;
public static readonly Day Sunday = 6;
private Day(int day)
{
this.day = day;
}
public static implicit operator int(Day value)
{
return value.day;
}
public static implicit operator Day(int value)
{
return new Day(value);
}
}
I created this utility to help me convert an Enum to PrimitiveEnum and PrimitiveEnum to byte, sbyte, short, ushort, int, uint, long, or ulong.
So, this technically converts any enum to any its primitive value.
public enum MyEnum
{
one = 1, two = 2
}
PrimitiveEnum number = MyEnum.one;
long i = number;
See commit at https://github.com/McKabue/McKabue.Extentions.Utility/blob/master/src/McKabue.Extentions.Utility/Enums/PrimitiveEnum.cs
using System;
namespace McKabue.Extentions.Utility.Enums
{
/// <summary>
/// <see href="https://stackoverflow.com/q/261663/3563013">
/// Can we define implicit conversions of enums in c#?
/// </see>
/// </summary>
public struct PrimitiveEnum
{
private Enum _enum;
public PrimitiveEnum(Enum _enum)
{
this._enum = _enum;
}
public Enum Enum => _enum;
public static implicit operator PrimitiveEnum(Enum _enum)
{
return new PrimitiveEnum(_enum);
}
public static implicit operator Enum(PrimitiveEnum primitiveEnum)
{
return primitiveEnum.Enum;
}
public static implicit operator byte(PrimitiveEnum primitiveEnum)
{
return Convert.ToByte(primitiveEnum.Enum);
}
public static implicit operator sbyte(PrimitiveEnum primitiveEnum)
{
return Convert.ToSByte(primitiveEnum.Enum);
}
public static implicit operator short(PrimitiveEnum primitiveEnum)
{
return Convert.ToInt16(primitiveEnum.Enum);
}
public static implicit operator ushort(PrimitiveEnum primitiveEnum)
{
return Convert.ToUInt16(primitiveEnum.Enum);
}
public static implicit operator int(PrimitiveEnum primitiveEnum)
{
return Convert.ToInt32(primitiveEnum.Enum);
}
public static implicit operator uint(PrimitiveEnum primitiveEnum)
{
return Convert.ToUInt32(primitiveEnum.Enum);
}
public static implicit operator long(PrimitiveEnum primitiveEnum)
{
return Convert.ToInt64(primitiveEnum.Enum);
}
public static implicit operator ulong(PrimitiveEnum primitiveEnum)
{
return Convert.ToUInt64(primitiveEnum.Enum);
}
}
}
If you define the base of the enum as a long then you can perform explicit conversion. I don't know if you can use implicit conversions as enums cannot have methods defined on them.
public enum MyEnum : long
{
one = 1,
two = 2,
}
MyEnum number = MyEnum.one;
long i = (long)number;
Also, be aware with this that an uninitalised enumeration will default to the 0 value, or the first item - so in the situation above it would probably be best to define zero = 0 as well.
I've worked around an issue with sehe's answer when running the code on MS .net (non-Mono). For me specifically the issue occurred on .net 4.5.1 but other versions seem affected, too.
The issue
accessing a public static TDervied MyEnumValue by reflection (via FieldInfo.GetValue(null) does not initialize said field.
The workaround
Instead of assigning names to TDerived instances upon the static initializer of RichEnum<TValue, TDerived> this is done lazily on first access of TDerived.Name. The code:
public abstract class RichEnum<TValue, TDerived> : EquatableBase<TDerived>
where TValue : struct, IComparable<TValue>, IEquatable<TValue>
where TDerived : RichEnum<TValue, TDerived>
{
// Enforcing that the field Name (´SomeEnum.SomeEnumValue´) is the same as its
// instances ´SomeEnum.Name´ is done by the static initializer of this class.
// Explanation of initialization sequence:
// 1. the static initializer of ´RichEnum<TValue, TDerived>´ reflects TDervied and
// creates a list of all ´public static TDervied´ fields:
// ´EnumInstanceToNameMapping´
// 2. the static initializer of ´TDerive´d assigns values to these fields
// 3. The user is now able to access the values of a field.
// Upon first access of ´TDervied.Name´ we search the list
// ´EnumInstanceToNameMapping´ (created at step 1) for the field that holds
// ´this´ instance of ´TDerived´.
// We then get the Name for ´this´ from the FieldInfo
private static readonly IReadOnlyCollection<EnumInstanceReflectionInfo>
EnumInstanceToNameMapping =
typeof(TDerived)
.GetFields(BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public)
.Where(t => t.FieldType == typeof(TDerived))
.Select(fieldInfo => new EnumInstanceReflectionInfo(fieldInfo))
.ToList();
private static readonly SortedList<TValue, TDerived> Values =
new SortedList<TValue, TDerived>();
public readonly TValue Value;
private readonly Lazy<string> _name;
protected RichEnum(TValue value)
{
Value = value;
// SortedList doesn't allow duplicates so we don't need to do
// duplicate checking ourselves
Values.Add(value, (TDerived)this);
_name = new Lazy<string>(
() => EnumInstanceToNameMapping
.First(x => ReferenceEquals(this, x.Instance))
.Name);
}
public string Name
{
get { return _name.Value; }
}
public static implicit operator TValue(RichEnum<TValue, TDerived> richEnum)
{
return richEnum.Value;
}
public static TDerived Convert(TValue value)
{
return Values[value];
}
protected override bool Equals(TDerived other)
{
return Value.Equals(other.Value);
}
protected override int ComputeHashCode()
{
return Value.GetHashCode();
}
private class EnumInstanceReflectionInfo
{
private readonly FieldInfo _field;
private readonly Lazy<TDerived> _instance;
public EnumInstanceReflectionInfo(FieldInfo field)
{
_field = field;
_instance = new Lazy<TDerived>(() => (TDerived)field.GetValue(null));
}
public TDerived Instance
{
get { return _instance.Value; }
}
public string Name { get { return _field.Name; } }
}
}
which - in my case - is based upon EquatableBase<T>:
public abstract class EquatableBase<T>
where T : class
{
public override bool Equals(object obj)
{
if (this == obj)
{
return true;
}
T other = obj as T;
if (other == null)
{
return false;
}
return Equals(other);
}
protected abstract bool Equals(T other);
public override int GetHashCode()
{
unchecked
{
return ComputeHashCode();
}
}
protected abstract int ComputeHashCode();
}
Note
The above code does not incorporate all features of Mark's original answer!
Thanks
Thanks to Mark for providing his RichEnum implementation and thanks to sehe for providing some improvements!
Here's a different flavour based on adminSoftDK's answer.
/// <summary>
/// Based on https://datatracker.ietf.org/doc/html/rfc4346#appendix-A.1
/// </summary>
[DebuggerDisplay("{_value}")]
public struct HandshakeContentType
{
#region Types
public const byte ChangeCipher = 0x14;
public const byte Alert = 0x15;
public const byte Handshake = 0x16;
public const byte ApplicationData = 0x17;
#endregion
byte _value;
private HandshakeContentType(byte value)
{
_value = value;
switch (_value)
{
case ChangeCipher:
case Alert:
case Handshake:
case ApplicationData:
break;
default:
throw new InvalidOperationException($"An invalid handshake content type (${value}) was provided.");
}
}
#region Methods
public static implicit operator byte(HandshakeContentType type) => type._value;
public static implicit operator HandshakeContentType(byte b) => new HandshakeContentType(b);
#endregion
}
This allows you to use this struct with switch statements which I think is pretty awesome.
#BatteryBackupUnit
Hey this sounds like a cool solution but could you explain this part here?
Since im getting with .NET 4.7.2 an "InvalidCastException" out of this sadly :/
_name = new Lazy<string>(
() => EnumInstanceToNameMapping
.First(x => ReferenceEquals(this, x.Instance))
.Name);
I dont know why, i have created a derived type of the RichEnum and initialized as everything u did in the example but i getthis annyoingg exception..
Would be glad of some help to this since i like this approach alot tbh.
I don't have enough rep to add a comment, but I was inspired by the 'struct' comment here:
https://stackoverflow.com/a/39141171/12135042
Here is how I did it:
public enum DaysOfWeek
{
Sunday = 0,
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 7,
}
public struct Weekends
{
private Weekends(DaysOfWeek day){ Day = day; }
public readonly DaysOfWeek Day;
public static Weekends Sunday = new(DaysOfWeek.Sunday);
public static Weekends Saturday = new(DaysOfWeek.Saturday);
public static implicit operator DaysOfWeek(Weekends value) => value.Mode;
}
I feel this gets the best of both worlds here, since you get your super enum, and easily accessible structs that are statically accessibly acting as subsets of the superenum.
Introducing implicit conversions for enum types would break type safety, so I'd not recommend to do that. Why would you want to do that? The only use case for this I've seen is when you want to put the enum values into a structure with a pre-defined layout. But even then, you can use the enum type in the structure and just tell the Marshaller what he should do with this.

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();

C# how to make a class that behave like Nullable<T>

Given the code:
public class Filter<T>
{
private bool selected = false;
public bool Selected { get { return selected; } }
private T value;
public T Value { get{ return this.value; } set { this.value = value; selected = true; }
}
public class Test
{
public void filter()
{
DateTime a= new DateTime();
Nullable<DateTime> b = new DateTime(); //Work Like a Charm
Filter<DateTime> c = new DateTime(); //Dosent Work
}
}
In Nullable<T> the new DateTime() can be assigned directly into the variable. In my class, it doesn't work. I want to understand what I'm missing.
I think that is something simple. But I couldn't put it on words to find the answer.
You have to implement implicit operators:
public static implicit operator Filter<T>(T value)
{
return new Filter<T>() { Value = value };
}
An implicit operator will allow you to cast the types without explicitly writing Filter<T> filter = (Filter<T>)value; (explicit cast), but rather only Filter<T> filter = value; (implicit cast).
You need to use an implict conversion operator:
See: Implicit cast operator and the equality operator
This allows you to write code to construct your custom type from another type.

Can enum represent string numbers?

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 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