Вы не заметите большой разницы в производительности между ними, но я по-прежнему рекомендую использовать словарь, потому что это даст вам немного большую гибкость в будущем.
С одной стороны, Enum в C# не может автоматически иметь ассоциированный с ним класс, как на Java, поэтому, если вы хотите связать дополнительную информацию с состоянием (полное имя, столичный город, сокращенная аббревиатура и т. Д.), , создавая класс UnitedState
, будет проще упаковать всю эту информацию в одну коллекцию.
Кроме того, даже если вы думаете это значение никогда не изменится, оно не является абсолютно неизменным. Можно, например, принять новое требование о включении территорий, например. Или, может быть, вам нужно будет позволить канадским пользователям видеть имена канадских провинций. Если вы рассматриваете эту коллекцию как любую другую коллекцию данных (используя репозиторий для извлечения значений из нее), позже вы сможете изменить реализацию репозитория, чтобы вытащить значения из другого источника (база данных, веб-служба, сеанс и т. Д.).). Перечисления гораздо менее универсальны.
Редактировать
Что касается аргумента производительности: Имейте в виду, что вы не просто отливку Enum к междунар: Вы также работаете ToString() на этом перечислении, который добавляет значительное время обработки. Рассмотрим следующий тест:
const int C = 10000;
int[] ids = new int[C];
string[] names = new string[C];
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i< C; i++)
{
var id = (i % 50) + 1;
names[i] = ((States)id).ToString();
}
sw.Stop();
Console.WriteLine("Enum: " + sw.Elapsed.TotalMilliseconds);
var namesById = Enum.GetValues(typeof(States)).Cast<States>()
.ToDictionary(s => (int) s, s => s.ToString());
sw.Restart();
for (int i = 0; i< C; i++)
{
var id = (i % 50) + 1;
names[i] = namesById[id];
}
sw.Stop();
Console.WriteLine("Dictionary: " + sw.Elapsed.TotalMilliseconds);
Результаты:
Enum: 26.4875
Dictionary: 0.7684
Так, если производительность действительно является вашей главной заботой, словарем, безусловно, путь. Тем не менее, мы говорим о таких быстрых временах здесь, что есть полдюжины других проблем, которые я бы затронул, прежде чем я даже позабочусь о проблеме скорости.
Перечисления в C# не предназначены для отображения сопоставлений между значениями и строками. Они были предназначены для обеспечения строго типизированных постоянных значений, которые вы можете передавать в коде. Два главных преимущества этого являются:
- У вас есть дополнительный ключ компилятора проверить, чтобы помочь вам избежать передачи аргументов в неправильном порядке, и т.д.
- Вместо того чтобы «магические» числовые значения (например, «42 ») в вашем коде, вы можете сказать« States.Oklahoma », что делает ваш код более читаемым.
В отличие от Java, C# не автоматически проверять значения броска, чтобы убедиться, что они являются действительными (myState = (States)321
), так что вы не получаете никаких проверок данных во время выполнения на входах, не делая их вручную. Если у вас нет кода, который явно ссылается на состояния («States.Oklahoma»), то вы не получите никакого значения из № 2 выше. Это оставляет нас с # 1 как единственной реальной причиной использования перечислений. Если это для вас достаточно хорошая причина, я бы предложил использовать перечисления вместо ints в качестве ваших ключевых значений. Затем, когда вам нужна строка или какое-то другое значение, связанное с состоянием, выполните поиск в Словаре.
Вот как я это сделать:
public enum StateKey{
AL = 1,AK,AS,AZ,AR,CA,CO,CT,DE,DC,FM,FL,GA,GU,
HI,ID,IL,IN,IA,KS,KY,LA,ME,MH,MD,MA,MI,MN,MS,
MO,MT,NE,NV,NH,NJ,NM,NY,NC,ND,MP,OH,OK,OR,PW,
PA,PR,RI,SC,SD,TN,TX,UT,VT,VI,VA,WA,WV,WI,WY,
}
public class State
{
public StateKey Key {get;set;}
public int IntKey {get {return (int)Key;}}
public string PostalAbbreviation {get;set;}
}
public interface IStateRepository
{
State GetByKey(StateKey key);
}
public class StateRepository : IStateRepository
{
private static Dictionary<StateKey, State> _statesByKey;
static StateRepository()
{
_statesByKey = Enum.GetValues(typeof(StateKey))
.Cast<StateKey>()
.ToDictionary(k => k, k => new State {Key = k, PostalAbbreviation = k.ToString()});
}
public State GetByKey(StateKey key)
{
return _statesByKey[key];
}
}
public class Foo
{
IStateRepository _repository;
// Dependency Injection makes this class unit-testable
public Foo(IStateRepository repository)
{
_repository = repository;
}
// If you haven't learned the wonders of DI, do this:
public Foo()
{
_repository = new StateRepository();
}
public void DoSomethingWithAState(StateKey key)
{
Console.WriteLine(_repository.GetByKey(key).PostalAbbreviation);
}
}
Таким образом:
- вы получите огибают строго типизированные значения, которые представляют собой состояние,
- ваш поиск получает fail- быстрое поведение, если ему задан недопустимый ввод,
- вы можете легко изменить, где фактические данные состояния находятся в будущем,
- вы можете легко добавить данные о состоянии в государственный класс в будущем,
- вы можете легко добавить новые состояния, территории, районы, провинции или что-то еще в будущем.
- Получение имени от int все еще около 15 раз быстрее, чем при использовании
Enum.ToString()
.
[ворчание]
Зачем вам нужно их бросать? – LukeH
@ LukeH: Предположительно потому, что в базе данных значения будут целыми. –
@ Jon: Это то, что я догадался, но было бы неплохо получить разъяснения от OP. – LukeH