Avatar ·

Как правильно инициализировать словарь Dictionary в C# с начальными значениями?

Всем привет! Я только начал изучать C# и столкнулся с проблемой при работе со словарями (Dictionary). Мне нужно создать словарь, в котором уже будут какие-то начальные значения, например, соответствия между кодами стран и их названиями. Я знаю, что можно сделать так: ```csharp var countries = new Dictionary(); countries.Add("RU", "Россия"); countries.Add("US", "США"); countries.Add("DE", "Германия"); ``` Но это занимает много строк, особенно если значений много. Я слышал, что в C# есть какой-то более короткий синтаксис для инициализации прямо при создании объекта. Пробовал писать что-то вроде: ```csharp var countries = new Dictionary { "RU" = "Россия", "US" = "США" }; ``` Но это не работает — компилятор ругается. Подскажите, пожалуйста, какой правильный синтаксис для инициализации словаря с начальными значениями? Есть ли разница между .NET Framework и .NET Core? И что делать, если я хочу инициализировать словарь не строковыми ключами, а, например, числами или перечислениями? Заранее спасибо за помощь! <<>>

Инициализация словаря с помощью синтаксиса коллекций

В C# существует элегантный способ инициализации словаря прямо в момент его создания. Правильный синтаксис использует фигурные скобки {} и пары "ключ-значение", разделённые запятыми. Каждая пара записывается как { ключ, значение } (обратите внимание: фигурные скобки для каждой пары, а не знак равенства).

var countries = new Dictionary<string, string>
{
    { "RU", "Россия" },
    { "US", "США" },
    { "DE", "Германия" },
    { "FR", "Франция" }
};

Синтаксис с индексатором (C# 6.0+)

Начиная с версии C# 6.0, появился ещё более лаконичный способ — с использованием индексатора [] прямо в инициализаторе:

var countries = new Dictionary<string, string>
{
    ["RU"] = "Россия",
    ["US"] = "США",
    ["DE"] = "Германия"
};

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

Инициализация с разными типами ключей

Словарь может использовать любые типы ключей — числа, перечисления, пользовательские классы (если они корректно реализуют GetHashCode и Equals). Примеры:

// Числовые ключи
var scores = new Dictionary<int, string>
{
    [1] = "Плохо",
    [2] = "Удовлетворительно",
    [3] = "Хорошо",
    [4] = "Отлично",
    [5] = "Великолепно"
};

// Ключи-перечисления
enum Status { Active, Inactive, Pending }

var statusDescriptions = new Dictionary<Status, string>
{
    [Status.Active] = "Активен",
    [Status.Inactive] = "Неактивен",
    [Status.Pending] = "Ожидание"
};

Инициализация пустого словаря и добавление позже

Если вам нужно создать пустой словарь, а затем заполнить его в цикле или по условию, используйте:

var config = new Dictionary<string, int>(); // пустой словарь
// или
var config = new Dictionary<string, int>(10); // с указанием начальной ёмкости для оптимизации

Важные замечания

  • Уникальность ключей: ключи в словаре должны быть уникальны. При инициализации вы получите исключение ArgumentException, если попытаетесь добавить дубликат.
  • Порядок элементов: в .NET Core и .NET 5+ словарь Dictionary<TKey, TValue> сохраняет порядок вставки элементов при переборе (но полагаться на это не рекомендуется). В .NET Framework порядок не гарантирован.
  • Регистр ключей: для строковых ключей по умолчанию учитывается регистр. Если нужно сравнивать без учёта регистра, используйте new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase).
  • Производительность: если вы заранее знаете количество элементов, передайте его в конструктор: new Dictionary<string, int>(100) — это уменьшит количество перестроений внутренней хеш-таблицы.

Полный пример

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // Инициализация через индексатор
        var capitals = new Dictionary<string, string>
        {
            ["Россия"] = "Москва",
            ["Франция"] = "Париж",
            ["Германия"] = "Берлин"
        };

        // Вывод
        foreach (var kvp in capitals)
        {
            Console.WriteLine($"{kvp.Key}: {kvp.Value}");
        }

        // Добавление нового элемента
        capitals["Италия"] = "Рим";

        // Безопасное получение значения
        if (capitals.TryGetValue("Россия", out string capital))
        {
            Console.WriteLine($"Столица России: {capital}");
        }
    }
}

Выберите тот синтаксис, который кажется вам более читаемым. Оба варианта корректны и широко используются в сообществе C# разработчиков.

<<>>

Альтернативный подход: инициализация через коллекцию пар KeyValuePair

Если вы предпочитаете более явный стиль, можно использовать коллекцию объектов KeyValuePair<TKey, TValue> и метод ToDictionary() из LINQ:

using System.Linq;

var countries = new List<KeyValuePair<string, string>>
{
    new KeyValuePair<string, string>("RU", "Россия"),
    new KeyValuePair<string, string>("US", "США")
}.ToDictionary(pair => pair.Key, pair => pair.Value);

Этот способ полезен, когда данные приходят из внешнего источника (например, из базы данных или JSON) в виде списка пар. Однако для простой инициализации он избыточен и менее производителен, чем прямые методы, описанные в основном ответе.

Инициализация из массива кортежей (C# 7.0+)

С появлением кортежей можно писать ещё короче, но с осторожностью — такой код может быть менее читаем для новичков:

var countries = new (string Key, string Value)[]
{
    ("RU", "Россия"),
    ("US", "США")
}.ToDictionary(t => t.Key, t => t.Value);

Рекомендую использовать стандартный синтаксис инициализатора { ключ, значение } или индексатор [ключ] = значение — это самый простой и надёжный способ для большинства задач.