Создание константного словаря в С#
Каков наиболее эффективный способ создания константы (никогда не изменяется во время выполнения), сопоставляющей string
с int
s?
Я пытался использовать const Dictionary, но это не сработало.
Я мог бы реализовать неизменяемую оболочку с соответствующей семантикой, но это все еще не совсем верно.
Для тех, кто спросил, я реализую IDataErrorInfo в сгенерированном классе и ищу способ сделать columnName поиском в моем массиве дескрипторов.
Я не знал (опечатка при тестировании! Черт!), Что переключатель принимает строки, так что я собираюсь использовать. Спасибо!
Ответы
Ответ 1
Создание подлинного словаря констант, сгенерированного во время компиляции, в С# - не простая задача. На самом деле, ни один из ответов здесь действительно не достигает этого.
Существует одно решение, которое соответствует вашим требованиям, хотя и не обязательно приятное; помните, что в соответствии со спецификацией С# таблицы switch-case скомпилированы в постоянные таблицы перехода хэша. То есть, они являются постоянными словарями, а не серией операторов if-else. Поэтому рассмотрим оператор switch-case следующим образом:
switch (myString)
{
case "cat": return 0;
case "dog": return 1;
case "elephant": return 3;
}
Это именно то, что вы хотите. И да, я знаю, это уродливо.
Ответ 2
В нынешних рамках существует немало неизменных коллекций. Я могу думать об одном безболезненном варианте в .NET 3.5:
Использовать Enumerable.ToLookup()
- класс Lookup<,>
является неизменным (но многозначным на rhs); вы можете сделать это с помощью Dictionary<,>
довольно легко:
Dictionary<string, int> ids = new Dictionary<string, int> {
{"abc",1}, {"def",2}, {"ghi",3}
};
ILookup<string, int> lookup = ids.ToLookup(x => x.Key, x => x.Value);
int i = lookup["def"].Single();
Ответ 3
enum Constants
{
Abc = 1,
Def = 2,
Ghi = 3
}
...
int i = (int)Enum.Parse(typeof(Constants), "Def");
Ответ 4
Это самая близкая вещь, которую вы можете получить в "Словарь CONST":
public static int GetValueByName(string name)
{
switch (name)
{
case "bob": return 1;
case "billy": return 2;
default: return -1;
}
}
Компилятор будет достаточно умным, чтобы сделать код максимально чистым.
Ответ 5
При использовании 4. 5+ Framework я использовал бы ReadOnlyDictionary (также ReadOnly Collection для списков), чтобы делать только для чтения отображения/константы. Это реализовано следующим образом.
static class SomeClass
{
static readonly ReadOnlyDictionary<string,int> SOME_MAPPING
= new ReadOnlyDictionary<string,int>(
new Dictionary<string,int>()
{
{ "One", 1 },
{ "Two", 2 }
}
)
}
Ответ 6
Почему бы не использовать пространства имен или классы для вложения ваших значений? Может быть несовершенным, но очень чистым.
public static class ParentClass
{
// here is the "dictionary" class
public static class FooDictionary
{
public const string Key1 = "somevalue";
public const string Foobar = "fubar";
}
}
Теперь вы можете получить доступ к .ParentClass.FooDictionary.Key1 и т.д.
Ответ 7
Кажется, что нет никакого стандартного неизменяемого интерфейса для словарей, поэтому создание оболочки, по-видимому, является единственным разумным вариантом.
Изменить: Марк Гравелл нашел ILookup, который я пропустил, - это позволит вам хотя бы избежать создания новой обертки, хотя вам все равно нужно преобразовать словарь с помощью .ToLookup().
Если это необходимо для определенного сценария, вам может быть лучше с более ориентированным на бизнес-логику интерфейсом:
interface IActiveUserCountProvider
{
int GetMaxForServer(string serverName);
}
Ответ 8
Я не уверен, почему никто не упомянул об этом, но в С# для вещей, которые я не могу назначить const, я использую статические свойства только для чтения.
Пример:
public static readonly Dictionary<string, string[]> NewDictionary = new Dictionary<string, string[]>()
{
{ "Reference1", Array1 },
{ "Reference2", Array2 },
{ "Reference3", Array3 },
{ "Reference4", Array4 },
{ "Reference5", Array5 }
};
Ответ 9
Почему бы и нет:
public class MyClass
{
private Dictionary<string, int> _myCollection = new Dictionary<string, int>() { { "A", 1 }, { "B", 2 }, { "C", 3 } };
public IEnumerable<KeyValuePair<string,int>> MyCollection
{
get { return _myCollection.AsEnumerable<KeyValuePair<string, int>>(); }
}
}