Использование 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)