Обновление: Посещение этой страницы, 8 лет спустя, после того, как долгое время не трогал C #, похоже, мой ответ больше не является лучшим решением. Мне очень нравится конвертер, связанный с атрибутами-функциями.
Если вы читаете это, убедитесь, что вы также ознакомились с другими ответами.
(подсказка: они выше этого)
Как и большинству из вас, мне действительно понравился выбранный ответ Якуба Штурца , но я также очень не хочу копировать-вставлять код и стараться делать это как можно меньше.
Поэтому я решил, что мне нужен класс EnumBase, от которого большая часть функциональных возможностей унаследована / встроена, и мне пришлось сосредоточиться на содержании, а не на поведении.
Основная проблема этого подхода основана на том факте, что, хотя значения Enum являются типобезопасными экземплярами, взаимодействие происходит со статической реализацией типа Enum Class.
Так что с небольшой помощью магии дженериков, я думаю, я наконец-то получил правильный микс.
Надеюсь, кто-то найдет это столь же полезным, как и я.
Начну с примера Якуба, но с использованием наследования и обобщений:
public sealed class AuthenticationMethod : EnumBase<AuthenticationMethod, int>
{
public static readonly AuthenticationMethod FORMS =
new AuthenticationMethod(1, "FORMS");
public static readonly AuthenticationMethod WINDOWSAUTHENTICATION =
new AuthenticationMethod(2, "WINDOWS");
public static readonly AuthenticationMethod SINGLESIGNON =
new AuthenticationMethod(3, "SSN");
private AuthenticationMethod(int Value, String Name)
: base( Value, Name ) { }
public new static IEnumerable<AuthenticationMethod> All
{ get { return EnumBase<AuthenticationMethod, int>.All; } }
public static explicit operator AuthenticationMethod(string str)
{ return Parse(str); }
}
А вот и базовый класс:
using System;
using System.Collections.Generic;
using System.Linq; // for the .AsEnumerable() method call
// E is the derived type-safe-enum class
// - this allows all static members to be truly unique to the specific
// derived class
public class EnumBase<E, T> where E: EnumBase<E, T>
{
#region Instance code
public T Value { get; private set; }
public string Name { get; private set; }
protected EnumBase(T EnumValue, string Name)
{
Value = EnumValue;
this.Name = Name;
mapping.Add(Name, this);
}
public override string ToString() { return Name; }
#endregion
#region Static tools
static private readonly Dictionary<string, EnumBase<E, T>> mapping;
static EnumBase() { mapping = new Dictionary<string, EnumBase<E, T>>(); }
protected static E Parse(string name)
{
EnumBase<E, T> result;
if (mapping.TryGetValue(name, out result))
{
return (E)result;
}
throw new InvalidCastException();
}
// This is protected to force the child class to expose it's own static
// method.
// By recreating this static method at the derived class, static
// initialization will be explicit, promising the mapping dictionary
// will never be empty when this method is called.
protected static IEnumerable<E> All
{ get { return mapping.Values.AsEnumerable().Cast<E>(); } }
#endregion
}