Использование Linq для объектов, как легко создать пустой словарь <string, string>?

Чтобы создать пустую последовательность, используйте следующие

var empty = Enumerable.Empty<string> ();

Есть ли эквивалент для создания пустого словаря так же легко, как это?

Ответы

Ответ 1

Нет эквивалента...

Цель Enumerable.Empty<T>() - вернуть "кешированный" экземпляр пустого массива. Таким образом, вы можете избежать накладных расходов на создание нового массива (return new T[0];).

Вы не можете перевести это на не-readonly структуру, такую ​​как IDictionary<TKey, TValue> или Dictionary<TKey, TValue>, поскольку возвращаемый экземпляр может быть изменен позже и поэтому приведет к недействительности цели...

Ответ 2

Что случилось с new Dictionary<string, string>()?

Ответ 3

Если ключ и значение имеют один и тот же тип (например: строка):

Enumerable.Empty<string>().ToDictionary(x=>x, x=>x)

Ответ 4

Я предполагаю, что (по крайней мере, сейчас 5 лет спустя) пустой словарь действительно означает пустой только для чтения словарь. Эта структура столь же полезна, как и пустая перечислимая последовательность. Например, у вас может быть тип конфигурации, обладающий свойством словаря (думаю, JSON), который не может быть изменен после его настройки:

public class MyConfiguration
{
    public IReadOnlyDictionary<string, string> MyProperty { get; set; }
}

Однако, что, если свойство никогда не настроено? Тогда MyProperty есть null. Хорошим решением избежать неожиданного NullReferenceException является инициализация свойства пустым словарем:

public class MyConfiguration
{
    public IReadOnlyDictionary<string, string> MyProperty { get; set; }
        = new Dictionary<string, string>();
}

Недостатком является то, что для каждого распределения MyConfiguration требуется выделение пустого словаря. Чтобы избежать этого, вам нужно что-то похожее на Enumerable.Empty<T>(), то есть кэшированный пустой словарь для чтения.

Есть два способа добиться этого. Первое заключается в том, чтобы зависеть от System.Collections.Immutable. ImmutableDictionary<TKey, TValue> реализует IReadOnlyDictionary<TKey, TValue> и имеет поле Empty, которое вы можете использовать:

IReadOnlyDictionary<string, string> empty = ImmutableDictionary<string, string>.Empty;

Или вы можете реализовать свой собственный пустой словарь для чтения, похожий на Enumerable.Empty<T>() и Array.Empty<T>(). Обратите внимание, как пустое значение больше не является полем и что класс не является общим. Вместо этого это общий метод. Для этого требуются два класса.

Первый класс "скрыт" и может быть внутренним:

internal static class EmptyReadOnlyDictionary<TKey, TValue>
{
    public static readonly IReadOnlyDictionary<TKey, TValue> Instance
        = new Dictionary<TKey, TValue>();
}

Второй класс использует первый класс, но скрывает его за интерфейсом IReadOnlyDictionary<TKey, TValue>:

public static class ReadOnlyDictionary
{
    public static IReadOnlyDictionary<TKey, TValue> Empty<TKey, TValue>()
        => EmptyReadOnlyDictionary<TKey, TValue>.Instance;
}

Использование:

IReadOnlyDictionary<string, string> empty = ReadOnlyDictionary.Empty<string, string>();

Для обоих решений будет только один пустой экземпляр словаря для каждой отдельной комбинации TKey и TValue.

Ответ 5

Enumerable.Empty<KeyValuePair<string, object>>().ToDictionary(kvp => kvp.Key, kvp => kvp.Value)