Вы не заметите большой разницы в производительности между ними, но я все равно рекомендую использовать словарь, потому что это даст вам немного больше гибкости в будущем.
С одной стороныEnum в C # не может автоматически иметь связанный с ним класс, как в Java, поэтому, если вы хотите связать дополнительную информацию с состоянием (ФИО, Столица, Почтовая аббревиатура и т. д.), создав класс UnitedState
упростит упаковку всей этой информации в одну коллекцию.
Кроме того, даже если вы думаете, это значение никогда не изменится, оно не является абсолютно неизменным.Например, у вас может появиться новое требование о включении территорий.Или, может быть, вам нужно разрешить канадским пользователям видеть названия канадских провинций.Если вы обрабатываете эту коллекцию как любую другую коллекцию данных (используя хранилище для извлечения значений из него), у вас позже будет возможность изменить реализацию хранилища, чтобы получать значения из другого источника (базы данных, веб-службы, сеанса и т. Д.).).Перечисления гораздо менее универсальны.
Редактировать
Относительно аргумента производительности: имейте в виду, что вы не просто приводите Enum к int: вы такжезапуск 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 в качестве единственной реальной причины для использования перечислений.Если это достаточно веская причина для вас, я бы предложил использовать перечисления вместо int в качестве значений ключа.Затем, когда вам понадобится строка или другое значение, связанное с состоянием, выполните поиск по словарю.
Вот как я это сделаю:
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);
}
}
Таким образом:
- вы можете передавать строго типизированные значения, представляющие состояние,
- ваш поиск будет работать без сбоев, если ему задан неверный ввод,
- вы можете легко изменитьесли фактические данные о состоянии находятся в будущем,
- вы можете легко добавлять данные о состоянии в класс State в будущем,
- вы можете легко добавлять новые штаты, территории, районы, провинцииили что-нибудь еще в будущем.
- получение имени от int все еще примерно в 15 раз быстрее , чем при использовании
Enum.ToString()
.
[grunt]