110

I have a small method that looks like this:

public void SetOptions<T>() where T : Enum
{
    int i = 0;
    foreach (T obj in Enum.GetValues(typeof(T)))
    {
        if (i == 0)
            DefaultOption = new ListItem(obj.Description(), obj.ToString());
        i++;
        DropDownList.Items.Add(new ListItem(obj.Description(), obj.ToString()));
    }
}

Basically, I populate a dropdown list from an enum. Description() is actually an extension method for enums, so T is definitely an enum.

However, I want to cast obj just as you would any enum to its index like this (int)obj, but I get an error saying I can't convert T to int. Is there a way to do this?

4
  • 7
    enum cannot be part of the generic constraint. Commented Jun 6, 2013 at 11:10
  • What is it exactly you are trying to accomplish? Populating the values of a drop down with the values from an enumerated type?
    – Roland Mai
    Commented Jun 6, 2013 at 11:30
  • I have a number of child usercontrols that all need to populate a base dropdownlist. The dropdownlist is on a base usercontrol. Previously the list was built in each of the child controls and then passed to the base usercontrol so no generics required. However looking to just pass the enum type and let the base control do the rest.
    – dotnetnoob
    Commented Jun 6, 2013 at 11:36
  • 12
    enum CAN be part of a generic type constraint as of May 7th, 2018 with the release of Visual Studio v15.7 with C# 7.3. stackoverflow.com/a/28527552/88409 However, this cast may still not be possible, haha.
    – Triynko
    Commented May 15, 2018 at 22:05

14 Answers 14

96

You could also cast your value to object first and then to int.

###C# 7.3 and above

With the Enum generic constraint.

public static int EnumToInt<TValue>(this TValue value) where TValue : Enum
    => (int)(object)value;

###Below C# 7.3

Without the Enum generic constraint.

public static int EnumToInt<TValue>(this TValue value)  where TValue : struct, IConvertible
{
    if(!typeof(TValue).IsEnum)
    {
        throw new ArgumentException(nameof(value));
    }

    return (int)(object)value;
}

If your enum inherits from other types for example from byte the cast to int will throw an InvalidCastException.

You could either check if the base type of the enum is an integer.

public static int EnumToInt<TValue>(this TValue value) where TValue : Enum
{
    if (!typeof(int).IsAssignableFrom(Enum.GetUnderlyingType(typeof(TValue))))
        throw new ArgumentException(nameof(TValue));

    return (int)(object)value;
}

Or you if you use Convert.ToInt32 it will use the IConvertible interface of int32 to convert the incompatible types.

public static int EnumToInt<TValue>(this TValue value) where TValue : Enum
    => Convert.ToInt32(value);

Just be aware the converting uint to int and signed/unsigned pairs can cause unintended behavior. (Boxing to IConvertible and the converting is less performant than just unboxing.)

4
  • Using the C# 7.3 approach I sometimes get InvalidCastException. VS's Immediate window says "Cannot convert type 'TValue' to 'int'" which is weird. The debugger window shows that the TValue value value in-memory is typed as the enum.
    – Dai
    Commented Sep 29, 2018 at 4:14
  • @Dai I've updated my answer to reflect your problems.
    – NtFreX
    Commented Oct 1, 2018 at 11:18
  • 1
    You can use (TEnum)(ValueType)value to avoid casting to object.
    – Ryan
    Commented Jun 22, 2021 at 6:45
  • 3
    @Ryan ValueType is also class, though, so it wouldn't avoid boxing anyway. Commented Jul 5, 2021 at 0:52
60

try this,

public void SetOptions<T>()
{
    Type genericType = typeof(T);
    if (genericType.IsEnum)
    {
        foreach (T obj in Enum.GetValues(genericType))
        {
            Enum test = Enum.Parse(typeof(T), obj.ToString()) as Enum;
            int x = Convert.ToInt32(test); // x is the integer value of enum
                        ..........
                        ..........
        }
    }
}
3
  • 1
    You can also add where T : struct, IComparable as a constraint so that only structs (like numbers and enums) can be passed in, just to limit it somewhat Commented Jul 11, 2016 at 1:59
  • 2
    Is not working if underlying type differs from int Commented Dec 23, 2016 at 13:35
  • 2
    Convert.ToInt32() is what does the trick.
    – InteXX
    Commented Aug 13, 2021 at 2:16
30

There are many answers to this question. I was interested in which solution works exactly the same as (int)enumValue and which is the fastest. So I wrote a benchmark using BenchmarkDotNet and checked also the results of used methods.

Performance Benchmark

Method Mean Error StdDev Median Gen 0 Allocated
Convert_ToInt32 20.4430 ns 0.1278 ns 0.1067 ns 20.4343 ns 0.0003 48 B
CastTo_Object_Int 8.3970 ns 0.0664 ns 0.0621 ns 8.3929 ns 0.0002 24 B
ByPointers_Switch_Byte 0.4515 ns 0.0035 ns 0.0029 ns 0.4512 ns - -
ByPointers_Switch_SByte 0.4664 ns 0.0069 ns 0.0064 ns 0.4687 ns - -
CompiledLambdaFunc 0.2236 ns 0.0055 ns 0.0051 ns 0.2230 ns - -
Unsafe_As 0.0045 ns 0.0050 ns 0.0047 ns 0.0034 ns - -
GetHashCode 0.0034 ns 0.0036 ns 0.0034 ns 0.0019 ns - -
ByPointers_DirectInt 0.0030 ns 0.0051 ns 0.0048 ns 0.0000 ns - -
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.22000
AMD Ryzen 9 5900HX with Radeon Graphics, 1 CPU, 16 logical and 8 physical cores
.NET SDK=6.0.300

Consistency with (int)enumValue

Method IntEnum UIntEnum LongEnum ULongEnum ByteEnum SByteEnum
Convert_ToInt32 ✓ same throws throws throws ✓ same ✓ same
CastTo_Object_Int ✓ same throws throws throws throws throws
ByPointers_Switch_Byte ✓ same ✓ same ✓ same ✓ same ✓ same differs*
ByPointers_Switch_SByte ✓ same ✓ same ✓ same ✓ same differs* ✓ same
CompiledLambdaFunc ✓ same ✓ same ✓ same ✓ same ✓ same ✓ same
Unsafe_As ✓ same ✓ same ✓ same ✓ same ✓ same ✓ same
GetHashCode ✓ same ✓ same differs differs ✓ same ✓ same
ByPointers_DirectInt ✓ same ✓ same ✓ same ✓ same ✓ same ✓ same
Legend:
✓ same:   gives the same results
throws:   throws an exception at least for some cases
differs:  gives different results at least for some cases
differs*: gives different results in Debug, same results in Release

A question regarding differs*: about *(byte*)(&sbyteValue) inconsistency in the Release mode.

Results

Two methods were both fastest and consistent with (int)enumValue:

public static int Unsafe_As<TEnum>(TEnum enumValue)
    where TEnum : struct, Enum
{
    return Unsafe.As<TEnum, int>(ref enumValue);
}

public static unsafe int ByPointers_DirectInt<TEnum>(TEnum enumValue)
    where TEnum : unmanaged, Enum
{
    return *(int*)(&enumValue);
}

The methods shall be safe and work well for TEnum : int, uint, long or ulong.

Caution: for TEnum : byte, sbyte, short or ushort these methods access more memory than is the native size of TEnum. If the extra memory is all '0', then we get the right results. But if not, then results end up corrupted.

I tried to make a failing example, but I failed. Anybody's suggestion or explanation is welcome.

Fastest among safe: The next fastest method gives exactly same results as (int)enumValue since it is a dynamically compiled version of this cast. If we consider full safety, then the CompiledLambdaFunc is the winner:

public static int CompiledLambdaFunc<TEnum>(TEnum value)
    where TEnum : struct, Enum
{
    return StaticGenericCache<TEnum>.TheFunc(value);
}

private static class StaticGenericCache<T>
    where T : struct, Enum
{
    public static Func<T, int> TheFunc = GenerateFunc<T>();
}

private static Func<TEnum, int> GenerateFunc<TEnum>()
    where TEnum : struct, Enum
{
    var inputParameter = Expression.Parameter(typeof(TEnum));

    var body = Expression.Convert(inputParameter, typeof(int)); // means: (int)input;

    var lambda = Expression.Lambda<Func<TEnum, int>>(body, inputParameter);

    var func = lambda.Compile();

    return func;
}

The Benchmark Code

[MemoryDiagnoser]
public class EnumToIntBenchmark
{
    [Benchmark]
    public int Convert_ToInt32() => Methods.Convert_ToInt32(SpecificEnum.TheValue);

    [Benchmark]
    public int CastTo_Object_Int() => Methods.CastTo_Object_Int(SpecificEnum.TheValue);

    [Benchmark]
    public int ByPointers_Switch_Byte() => Methods.ByPointers_Switch_Byte(SpecificEnum.TheValue);

    [Benchmark]
    public int ByPointers_Switch_SByte() => Methods.ByPointers_Switch_SByte(SpecificEnum.TheValue);

    [Benchmark]
    public int CompiledLambdaFunc() => Methods.CompiledLambdaFunc(SpecificEnum.TheValue);

    [Benchmark]
    public int Unsafe_As() => Methods.Unsafe_As(SpecificEnum.TheValue);

    [Benchmark]
    public new int GetHashCode() => Methods.GetHashCode(SpecificEnum.TheValue);

    [Benchmark]
    public int ByPointers_DirectInt() => Methods.ByPointers_DirectInt(SpecificEnum.TheValue);

    private enum SpecificEnum
    {
        None = 0,
        TheValue,
    }

    public static class Methods
    {
        public static int Convert_ToInt32<TEnum>(TEnum value)
            where TEnum : struct, Enum
        {
            return Convert.ToInt32(value);
        }

        public static int CastTo_Object_Int<TEnum>(TEnum value)
            where TEnum : struct, Enum
        {
            return (int)(object)value;
        }

        public static unsafe int ByPointers_Switch_Byte<TEnum>(TEnum enumValue)
            where TEnum : unmanaged, Enum
        {
            switch (sizeof(TEnum))
            {
                case 1:  return *(byte*)(&enumValue);
                case 2:  return *(short*)(&enumValue);
                case 4:  return *(int*)(&enumValue);
                case 8:  return (int)*(long*)(&enumValue);
                default: throw new NotImplementedException($"Not implemented for size: {sizeof(TEnum)}");
            }
        }

        public static unsafe int ByPointers_Switch_SByte<TEnum>(TEnum enumValue)
            where TEnum : unmanaged, Enum
        {
            switch (sizeof(TEnum))
            {
                case 1:  return *(sbyte*)(&enumValue);
                case 2:  return *(short*)(&enumValue);
                case 4:  return *(int*)(&enumValue);
                case 8:  return (int)*(long*)(&enumValue);
                default: throw new NotImplementedException($"Not implemented for size: {sizeof(TEnum)}");
            }
        }

        public static unsafe int ByPointers_DirectInt<TEnum>(TEnum enumValue)
            where TEnum : unmanaged, Enum
        {
            return *(int*)(&enumValue);
        }

        public static int Unsafe_As<TEnum>(TEnum enumValue)
            where TEnum : struct, Enum
        {
            return Unsafe.As<TEnum, int>(ref enumValue);
        }

        public static int GetHashCode<TEnum>(TEnum value)
            where TEnum : struct, Enum
        {
            return value.GetHashCode();
        }

        public static int CompiledLambdaFunc<TEnum>(TEnum value)
            where TEnum : struct, Enum
        {
            return StaticGenericCache<TEnum>.TheFunc(value);
        }

        private static class StaticGenericCache<T>
            where T : struct, Enum
        {
            public static Func<T, int> TheFunc = GenerateFunc<T>();
        }

        private static Func<TEnum, int> GenerateFunc<TEnum>()
            where TEnum : struct, Enum
        {
            var inputParameter = Expression.Parameter(typeof(TEnum));

            var body = Expression.Convert(inputParameter, typeof(int)); // means: (int)input;

            var lambda = Expression.Lambda<Func<TEnum, int>>(body, inputParameter);

            var func = lambda.Compile();

            return func;
        }
    }
}

The Consistency Check Table Code

class Program
{
    static void Main()
    {
        var table = GenerateConsistencyTable();

        Console.WriteLine(table);
    }

    private static string GenerateConsistencyTable()
    {
        var sb = new StringBuilder();

        sb.AppendLine(GenerateHeader());
        sb.AppendLine(GenerateUnderHeader());

        foreach (var methodName in _methodNames)
        {
            sb.AppendLine(CheckAllEnumsForMethod(methodName));
        }

        return sb.ToString().Trim();
    }

    private static readonly string[] _methodNames = new string[]
    {
        nameof(EnumToIntBenchmark.Methods.Convert_ToInt32),
        nameof(EnumToIntBenchmark.Methods.CastTo_Object_Int),
        nameof(EnumToIntBenchmark.Methods.ByPointers_Switch_Byte),
        nameof(EnumToIntBenchmark.Methods.ByPointers_Switch_SByte),
        nameof(EnumToIntBenchmark.Methods.CompiledLambdaFunc),
        nameof(EnumToIntBenchmark.Methods.Unsafe_As),
        nameof(EnumToIntBenchmark.Methods.GetHashCode),
        nameof(EnumToIntBenchmark.Methods.ByPointers_DirectInt),
    };

    private static readonly Type[] _allEnumTypes = new Type[] { typeof(IntEnum), typeof(UIntEnum), typeof(LongEnum), typeof(ULongEnum), typeof(ByteEnum), typeof(SByteEnum) };

    private static string GenerateHeader()
    {
        var line = $"| {"Method",30} ";

        foreach (var enumType in _allEnumTypes)
        {
            line += $"| {enumType.Name,10} ";
        }

        line += '|';

        return line;
    }

    private static string GenerateUnderHeader()
    {
        var line = '|' + new string('-', 32);

        foreach (var enumType in _allEnumTypes)
        {
            line += '|' + new string('-', 11) + ':';
        }

        line += '|';

        return line;
    }

    private static string CheckAllEnumsForMethod(string methodName)
    {
        var line = $"| {methodName,30} ";

        foreach (var enumType in _allEnumTypes)
        {
            line += $"| {CheckMethodAndEnum(enumType, methodName),10} ";
        }

        line += '|';

        return line;
    }

    private static string CheckMethodAndEnum(Type enumType, string methodName)
    {
        var methodsClassType = typeof(EnumToIntBenchmark.Methods);
        var methodInfoGeneric = methodsClassType.GetMethods().Single(method => method.Name == methodName && method.IsGenericMethodDefinition);
        var methodInfoSpecific = methodInfoGeneric!.MakeGenericMethod(enumType);

        var funcType = typeof(Func<,>).MakeGenericType(enumType, typeof(int));
        var methodFuncDelegate = Delegate.CreateDelegate(funcType, methodInfoSpecific);
        var methodFunc = Convert.ChangeType(methodFuncDelegate, funcType);

        var checkMethodGeneric = typeof(Program).GetMethod(nameof(CheckMethodAndEnumCore), BindingFlags.Static | BindingFlags.NonPublic);
        var checkMethod = checkMethodGeneric!.MakeGenericMethod(enumType);

        return (string)checkMethod.Invoke(null, new object?[] { methodFunc })!;
    }

    private static string CheckMethodAndEnumCore<TEnum>(Func<TEnum, int> method)
        where TEnum : struct, Enum
    {
        bool anyIsDifferent = false;

        try
        {
            var allEnumValues = Enum.GetValues<TEnum>();

            foreach (var enumValue in allEnumValues)
            {
                var expected = RealCastToInt(enumValue);
                var actual = method(enumValue);

                if (expected != actual)
                {
                    anyIsDifferent = true;
                }
            }
        }
        catch (Exception e)
        {
            return "throws";
        }

        return anyIsDifferent ? "differs" : "\u2713 same";
    }

    private static int RealCastToInt<TEnum>(TEnum enumValue)
        where TEnum : struct, Enum
    {
        switch (enumValue)
        {
            case IntEnum typedValue:   return (int)typedValue;
            case LongEnum typedValue:  return (int)typedValue;
            case UIntEnum typedValue:  return (int)typedValue;
            case ULongEnum typedValue: return (int)typedValue;
            case ByteEnum typedValue:  return (int)typedValue;
            case SByteEnum typedValue: return (int)typedValue;
            default:                   throw new NotImplementedException($"Not implemented for type: {typeof(TEnum)}");
        }
    }

    enum IntEnum : int
    {
        None = 0,
        One = 1,
        MinusOne = -1,
        MinValue = int.MinValue,
        MaxValue = int.MaxValue,
    }

    enum LongEnum : long
    {
        None = 0,
        One = 1,
        MinusOne = -1,
        MinValue = long.MinValue,
        MaxValue = long.MaxValue,
    }

    enum UIntEnum : uint
    {
        None = 0,
        One = 1,
        MinValue = uint.MinValue,
        MaxValue = uint.MaxValue,
    }

    enum ULongEnum : ulong
    {
        None = 0,
        One = 1,
        MinValue = ulong.MinValue,
        MaxValue = ulong.MaxValue,
    }

    enum ByteEnum : byte
    {
        None = 0,
        One = 1,
        MinValue = byte.MinValue,
        MaxValue = byte.MaxValue,
    }

    enum SByteEnum : sbyte
    {
        None = 0,
        One = 1,
        MinusOne = -1,
        MinValue = sbyte.MinValue,
        MaxValue = sbyte.MaxValue,
    }
}
15

If you are targeting .NET Core, you can utilize Unsafe.As<TFrom, TTo> in the System.Runtime.CompilerServices namespace, as explained on MSDN. The advantage here is there will be no boxing done, which is the only real performance cost in the other answers here.

private static int EnumToInt<TEnum>(TEnum enumValue) where TEnum : Enum
{
    return Unsafe.As<TEnum, int>(ref enumValue);
}

Note that this approach suffers from the safe issue as other existing answers do: there is not a guarantee that the given enum is a compatible int type, which is likely the same reason this functionality is not baked-in. If you are using this approach internally where you can be sure that any enum passed to it is a compatible type, then this is likely the most efficient approach.

Here is a link to an issue on dotnet's GitHub page where where this issue was raised, and some of the developers elaborated a bit on this approach if you would like to learn more.

2
  • I wonder how did you compile this snippet because the signature and explanation looks quite differently. "Reinterprets the given managed pointer as a new managed pointer to a value of type TTo." Commented Sep 1, 2022 at 17:00
  • 1
    @greenoldman There was a missing usage of ref in the example. Commented Sep 2, 2022 at 20:10
8

Here's my solution for C# 7.3 and up. Not an exact match to OP's question, but probably useful for people finding this from Google. The main advantage over the other answers is it returns a ulong, which means any of the permissible enum types will fit in it. I also made a comparison of the machine code for this and a few of the other answers. Yes, I was bored and in the mood for a little premature optimization.

private static unsafe ulong EnumAsUInt64<T>(T item) where T : unmanaged, Enum
{
    ulong x;
    if (sizeof(T) == 1)
        x = *(byte*)(&item);
    else if (sizeof(T) == 2)
        x = *(ushort*)(&item);
    else if (sizeof(T) == 4)
        x = *(uint*)(&item);
    else if (sizeof(T) == 8)
        x = *(ulong*)(&item);
    else
        throw new ArgumentException("Argument is not a usual enum type; it is not 1, 2, 4, or 8 bytes in length.");
    return x;
}
5

This one is working with any underlying type

Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType()))

For example when you want add a value to SqlCommand, which converts enums to 0 and you have to explicitly cast it to matching type. But we can write following extension:

public static void AddEnum(this SqlParameterCollection parameters, string parameterName, Enum value)
{
    parameters.AddWithValue(parameterName, Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType())));
}

Which is doing everything for us.

4

Can you abuse GetHashCode for this?

public enum MyEnum
{
  Foo = 100,
  Bar = 200,
  Fizz = 0
}

static void Main(string[] args)
{
  var i1 = MyEnum.Foo.GetHashCode();  // i1 = 100
  var i2 = MyEnum.Bar.GetHashCode();  // i2 = 200
  var i3 = MyEnum.Fizz.GetHashCode(); // i3 = 0
}

Please note: "GetHashCode() is by design useful for only one thing: putting an object in a hash table. Hence the name." - E. Lippert

6
  • 1
    There is no guarantee that GetHashCode always returns the underlying integer or that its implementation will remain the same between .NET versions. That said, I don't see why they'd ever change it. Commented Feb 13, 2016 at 15:23
  • Is GetHashCode() secure to use as a dictionary key in stead of an int cast for enums?
    – noio
    Commented Feb 18, 2016 at 17:46
  • 1
    @noio GetHashCode() is "by design useful for only one thing: putting an object in a hash table" (said E. Lippert himself) (which invalidates my own answer btw) I guess it is safe, but I wouldn't use it for creating keys for use in a dictionary: why not just use the enums as-is?
    – jan
    Commented Feb 19, 2016 at 14:30
  • There is an issue with Boxing when the dict key is a generic type (Dictionary<TEnum, string>) constrained by class MyClass<TEnum> where TEnum: struct, IComparable in the generic class definition (which I know to be an Enum, but not which enum). So instead I created a Dictionary<int, string> and do a manual myDictionary[myEnumValue.GetHashCode()] everywhere.
    – noio
    Commented Feb 20, 2016 at 15:32
  • @noio If you don't know which enum, then you also can't know that the enum values won't collide since different enums can use the same numeric value. I suggest using the closed type (i.e. MyClass<SomeState>) as the dictionary key -or- if you define all the enums and give each a specific range, you may consider merging them into one. Commented Dec 4, 2017 at 12:34
4

if you restict the generic T to be an Enum using

where T: Enum

you can then use the one-liner below

public static int GetIndexFromEnum<T>(T enumValue) where T : Enum {
    int index = Convert.ToInt32(enumValue);
    return index;
}

This seems like the simplest solution, as long as you can guarantee T is going to be an Enum.

4

Here's a simpler way.

Since Enum implements IConvertible we can use ToInt32(..).

int? value = (enumCandidate as IConvertible)?.ToInt32(CultureInfo.InvariantCulture.NumberFormat);

Or if you'd like a general purpose method for generic enums:

public static int GetEnumValue<T>(T inputEnum) where T: struct, IConvertible
{
    Type t = typeof(T);
    if (!t.IsEnum)
    {
        throw new ArgumentException("Input type must be an enum.");
    }

    return inputEnum.ToInt32(CultureInfo.InvariantCulture.NumberFormat);

}

Or yet more general:

public static int GetEnumValue(object enumInput)
{
    Type t = enumInput.GetType();
    if (!t.IsEnum)
    {
        throw new ArgumentException("Input type must be an enum.");
    }

    return ((IConvertible)inputEnum).ToInt32(CultureInfo.InvariantCulture.NumberFormat);

}
3

Just cast the generic T to object first

T value;
int int_value = (int)(object)value;

That's it.

1
  • This is very similar to @NtFreX‘s answer from two years ago, except they provide more explanation and also address how to handle cases where the code is written for earlier versions of C#. Commented May 20, 2020 at 8:38
1

I'm surprised your code works at all. Enum.GetValues returns an array of integers - which are the values you're looking for. And, as others have mentioned, you can't constrain your generics to an enum.

Instead, you should probably call your Description method as a regular static method and not an extension method.

5
  • I don't understand this answer. Could you elaborate some more .. ?
    – Ken Kin
    Commented Jun 6, 2013 at 11:13
  • 2
    His method doesn't work, because public void SetOptions<T>() where T : Enum simply won't compile Commented Jun 6, 2013 at 11:16
  • I'm just building the method now, so I haven't compiled as yet as I came across the casting issue.
    – dotnetnoob
    Commented Jun 6, 2013 at 11:19
  • @IlyaIvanov: I can understand about the problem of that constraint, what I don't understand is how's the answer answers the question though ..
    – Ken Kin
    Commented Jun 6, 2013 at 11:47
  • The ability to constrain generic types to be Enums is coming soon to C#. Commented May 21, 2018 at 18:38
1

Using LINQ this can be done elegantly:

public static void SetOptions<T>(this DropDownList dropDownList)
{
    if (!typeof(T).IsEnum)
    {
        throw new ArgumentException("Type must be an enum type.");
    }

    dropDownList.Items.AddRange(Enum
        .GetValues(typeof(T))
        .Cast<Enum>()
        .Select(x => new ListItem(x.ToString(), Convert.ToInt32(x).ToString()))
        .ToArray());
}
0

Try this: (assuming that the TEnum has a numeration from 0 to n)

public void SetOptions<TEnum>() where TEnum : Enum
{
    foreach (TEnum obj in Enum.GetValues(typeof(TEnum)))
    {
        var i = (int)(object)obj;
        if (i == 0) DefaultOption = new ListItem(obj.Description(), obj.ToString());
        DropDownList.Items.Add(new ListItem(obj.Description(), obj.ToString()));
    }
}
-3

To expand on Jan's answer concerning generics and enum values:

void MyFunc<T>(T value)
{
    Type t = typeof(T);
    if(t.IsEnum)
    {
        int valueAsInt = value.GetHashCode(); // returns the integer value
    }
}
1
  • 2
    Doesn't this assume that Enum.GetUnderlyingType() is actually an int. If you happen to be using public enum : long { } for any reason, you are going to be compacting an 8-byte value into a 4-byte one... Commented Nov 12, 2015 at 17:13

Not the answer you're looking for? Browse other questions tagged or ask your own question.