2010-02-18 2 views
3

Возьмите это перечисление, например:Помощь в создании Enum расширения помощник

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

I wnat иметь ен метод расширения, как это:

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

Любая идея, как это реализовать?

он должен быть общим для int, short и т. Д., А также для общих перечислений, а не только для PersonName.

+0

Что вы спрашиваете? – SLaks

+0

Это невозможно сделать. (Вы не можете создать метод, основанный на базовом типе 'enum'). – SLaks

+0

Зачем вам нужен метод расширения? Кастинг для базового типа уже прост, как '(int) SomeEnum.SomeValue' –

ответ

2

Это совершенно невозможно.

Вы не можете ограничить метод, основанный на базовом типе enum.

Объяснение:

Вот как вы могли бы попытаться сделать это:

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

Первое ограничение unfortunately not allowed by C#, а второе ограничение не поддерживается CLR.

+0

Вы можете «сортировать» (ну, вы создаете эффект) - http://msmvps.com/blogs/jon_skeet/archive/2009/09/10/generic-constraints-for-enums-and-delegates.aspx – adrianbanks

+0

См. Также: http://stackoverflow.com/questions/7244/anyone-know-a-good-workaround-for-the-lack-of-an-enum-generic-constraint –

0

Я считаю, что вы должны быть в состоянии определить метод расширения на PersonName класса:

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

Боковой узел: Я как-то надеюсь, что код в ваш вопрос слишком упрощенным, поскольку это, кажется, не совсем право на внедрение репозитория лица в качестве перечисления :)

+0

Я хочу, чтобы он был общим. и, конечно, это был пример :) –

+0

Извините, не поймал это в вашем вопросе. Я боюсь, что я не уверен, что вы подразумеваете под «родовым» в этом контексте, но, похоже, другие выяснили это :) –

0

Есть ли причина, по которой вы не можете превратить ее в класс? Вероятно, это будет иметь смысл в контексте класса.

+0

Хорошая точка. И как получить имя человека-собственности, используя reflation? или каждый должен возвращать словарь? Я подумаю об этом. вопрос, который мне еще интересен. –

0

Я бы просто использовал что-то вроде IEnumerable<KeyValuePair<string,short>> или Dictionary<string,short> ... вы можете добавить свои расширения в IDictionary или IEnumerable, если хотите.

+0

Это то, что я сейчас буду использовать. Но насчет вопроса, такого поведения я хотел много времени, но, насколько мне известно, этого достичь не удалось. –

2

Ну, его вид можно, но с другой стороны вы должны указать, какой именно тип:

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

System.Enum, поскольку является базовым классом для всех типов перечислений. Назовите это:

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

Так как вы можете бросить почти ничего long, вы могли бы даже это:

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

и называют:

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

Что в противном случае возможно это получить object экземпляр возвращен, например, тот или иной:

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? 

Все это связано с каким-то боксом и распаковкой. Второй подход выглядит лучше (вы даже можете сделать его int, стандартный тип), а затем первый.

Смежные вопросы