Создание постоянного словаря в C # - PullRequest
109 голосов
/ 06 ноября 2008

Каков наиболее эффективный способ создания константы (никогда не изменяется во время выполнения) для отображения string с int с?

Я пытался использовать const Dictionary , но это не сработало.

Я мог бы реализовать неизменяемую оболочку с соответствующей семантикой, но это все еще не совсем верно.


Для тех, кто спросил, я реализую IDataErrorInfo в сгенерированном классе и ищу способ сделать поиск columnName моим массивом дескрипторов.

Я не знал (опечатка при тестировании! Черт!), Что переключатель принимает строки, так что это то, что я собираюсь использовать. Спасибо!

Ответы [ 8 ]

157 голосов
/ 06 ноября 2008

Создание действительно генерируемого словаря констант во время компиляции в C # на самом деле не простая задача. На самом деле, ни один из ответов здесь действительно не достигает этого.

Существует одно решение, которое соответствует вашим требованиям, хотя не обязательно хорошее; помните, что в соответствии со спецификацией C # таблицы переключателей компилируются в таблицы с постоянными хэш-переходами. То есть они являются постоянными словарями, а не серией утверждений if-else. Итак, рассмотрим оператор switch-case следующим образом:

switch (myString)
{
   case "cat": return 0;
   case "dog": return 1;
   case "elephant": return 3;
}

Это именно то, что вы хотите. И да, я знаю, это ужасно.

35 голосов
/ 06 ноября 2008

В нынешней структуре очень мало неизменных коллекций. Я могу вспомнить один относительно безболезненный вариант в .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();
14 голосов
/ 06 ноября 2008
enum Constants
{
    Abc = 1,
    Def = 2,
    Ghi = 3
}

...

int i = (int)Enum.Parse(typeof(Constants), "Def");
10 голосов
/ 06 ноября 2008

Это самая близкая вещь, которую вы можете найти в «Словаре CONST»:

public static int GetValueByName(string name)
{
    switch (name)
    {
        case "bob": return 1;
        case "billy": return 2;
        default: return -1;
    }
}

Компилятор будет достаточно умен, чтобы сделать код максимально чистым.

3 голосов
/ 30 октября 2018

Если использовать 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 }
            }
        )
}        
2 голосов
/ 10 апреля 2018

Почему бы не использовать пространства имен или классы для вложения ваших значений? Может быть несовершенным, но очень чистым.

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 и т. Д.

1 голос
/ 06 ноября 2008

Кажется, что нет никакого стандартного неизменяемого интерфейса для словарей, поэтому создание оболочки, к сожалению, кажется единственно разумным вариантом.

Редактировать : Марк Гравелл обнаружил пропущенную мной ILookup, которая позволит вам по крайней мере избежать создания новой оболочки, хотя вам все равно нужно преобразовать словарь с помощью .ToLookup ().

Если эта необходимость ограничена конкретным сценарием, возможно, вам лучше использовать интерфейс, более ориентированный на бизнес-логику:

interface IActiveUserCountProvider
{
    int GetMaxForServer(string serverName);
}
0 голосов
/ 27 июля 2010

Почему бы и нет:

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>>(); }
    }
}
...