3

Take this enum for example:

public enum PersonName : short
{
    Mike = 1,
    Robert= 2
}

I wnat to have en extension method like this:

PersonName person = PersonName.Robert;
short personId = person.GetId();
//Instead of:
short personId = (short)person;

Any idea how to implement this?

it need to be generic to int, short etc..., and to generic enums as well, not limited to PersonName.

Fitzchak Yitzchaki
  • 9,095
  • 12
  • 56
  • 96
  • This is not possible to do. (You cannot constain a method based on an `enum`'s underlying type) – SLaks Feb 18 '10 at 22:53
  • Why would you need an extension method to do this? Casting to the underlying type is already as easy as `(int) SomeEnum.SomeValue` – Jørn Schou-Rode Feb 19 '10 at 08:07

5 Answers5

2

Well, its sort of possible, but on the flip side you will have to specify what the underlying type is:

public static T GetId<T>(this Enum value) 
                        where T : struct, IComparable, IFormattable, IConvertible
{
    return (T)Convert.ChangeType(value, typeof(T));
}

since System.Enum is the base class of all enum types. Call it:

PersonName person = PersonName.Robert;
short personId = person.GetId<short>();

Since you can cast almost anything to long, you could even have this:

public static long GetId(this Enum value)
{
    return Convert.ToInt64(value);
}

and call:

PersonName person = PersonName.Robert;
long personId = person.GetId();

What is otherwise possible is to get an object instance returned, like this or so:

public static object GetId(this Enum value)
{
    return Convert.ChangeType(task, Enum.GetUnderlyingType(value.GetType()));
}

PersonName person = PersonName.Robert;
var personId = (short)person.GetId(); 
// but that sort of defeats the purpose isnt it?

All of which involves some sort of boxing and unboxing. The second approach looks better (you could even make it int, the standard type) and then the first.

nawfal
  • 70,104
  • 56
  • 326
  • 368
2

This is completely impossible.

You cannot constrain a method based on an enum's underlying type.

Explanation:

Here is how you might try to do this:

public static TNumber GetId<TEnum, TNumber>(this TEnum val) 
       where TEnum : Enum 
       where TEnum based on TNumber

The first constraint is unfortunately not allowed by C#, and the second constraint is not supported by the CLR.

Community
  • 1
  • 1
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • You can "sort of" (well, you create the effect) - http://msmvps.com/blogs/jon_skeet/archive/2009/09/10/generic-constraints-for-enums-and-delegates.aspx – adrianbanks Feb 18 '10 at 23:07
  • See also: http://stackoverflow.com/questions/7244/anyone-know-a-good-workaround-for-the-lack-of-an-enum-generic-constraint – Jørn Schou-Rode Feb 19 '10 at 08:08
0

I believe you should be able to define an extension method on the PersonName class:

public static class PersonExtensions // now that sounds weird...
{
    public static short GetID (this PersonName name)
    {
        return (short) name;
    }
}

Side node: I somehow hope that the code in your question is overly simplified, as it does not seem quite right to implement a person repository as an enum :)

Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
Jørn Schou-Rode
  • 37,718
  • 15
  • 88
  • 122
0

Is there any reason you can't turn it into a class? It would probably make more sense in context of a class.

Zach Johnson
  • 23,678
  • 6
  • 69
  • 86
  • Good point. And how get the person-property name, using reflation? or each one should return dictionary? I'll think about it. bu the question still interesting to me. – Fitzchak Yitzchaki Feb 18 '10 at 22:52
0

I would just use something like IEnumerable<KeyValuePair<string,short>> or Dictionary<string,short>... you can add your extensions to IDictionary or IEnumerable if you want.

Perpetualcoder
  • 13,501
  • 9
  • 64
  • 99
  • That what I'm going to use by now. But about the question, this behavior I wanted a lot of time, but from my knowledge it not possible to achieve. – Fitzchak Yitzchaki Feb 18 '10 at 22:55