Создание константного словаря в С#

Каков наиболее эффективный способ создания константы (никогда не изменяется во время выполнения), сопоставляющей 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>>(); }
    }
}