Как создать пустой IReadOnlyCollection
Я создаю метод расширения для MultiValueDictionary для инкапсуляции частых проверок ContainsKey
, и мне было интересно, что было лучшим способом создать пустой IReadOnlyCollection
?.
То, что я использовал до сих пор, это new List<TValue>(0).AsReadOnly()
, но должен быть лучший способ, эквивалент IEnumerable
Enumerable.Empty
public static IReadOnlyCollection<TValue> GetValuesOrEmpty<TKey, TValue>(this MultiValueDictionary<TKey, TValue> multiValueDictionary, TKey key)
{
IReadOnlyCollection<TValue> values;
return !multiValueDictionary.TryGetValue(key, out values) ? new List<TValue>(0).AsReadOnly() : values;
}
Ответы
Ответ 1
EDIT: новый .Net 4.6 добавляет API для получения пустого массива: Array.Empty<T>
и массивы реализуют IReadOnlyCollection<T>
. Это также уменьшает выделение, поскольку оно создает экземпляр только один раз:
IReadOnlyCollection<int> emptyReadOnlyCollection = Array.Empty<int>();
То, что я закончил, это подражать реализации Enumerable.Empty
с помощью new TElement[0]
:
public static class ReadOnlyCollection
{
public static IReadOnlyCollection<TResult> Empty<TResult>()
{
return EmptyReadOnlyCollection<TResult>.Instance;
}
private static class EmptyReadOnlyCollection<TElement>
{
static volatile TElement[] _instance;
public static IReadOnlyCollection<TElement> Instance
{
get { return _instance ?? (_instance = new TElement[0]); }
}
}
}
Использование:
IReadOnlyCollection<int> emptyReadOnlyCollection = ReadOnlyCollection.Empty<int>();
Ответ 2
Я не думаю, что есть что-то вроде Enumerable.Empty
для коллекций только для чтения, но:
-
List<T>
уже реализует IReadOnlyCollection<T>
, поэтому вы можете избежать выделения одного объекта, не вызывая AsReadOnly()
и просто вместо этого списывая список. Это менее "безопасно" теоретически, но практически не имеет практического значения.
-
Кроме того, вы можете кэшировать возвращаемый ReadOnlyCollection, чтобы избежать любого размещения объекта (кроме кэшированного объекта).
Ответ 3
Насколько я знаю, нет встроенного способа (интересно знать, если таковое). При этом вы можете использовать следующее:
IReadOnlyCollection<TValue> readonlyCollection = new ReadOnlyCollection<TValue>(new TValue[] { });
По желанию вы можете кэшировать результаты, поскольку это ReadOnlyCollection
поверх пустого массива. Он всегда будет таким же, независимо от того, сколько у вас экземпляров.
Ответ 4
Как насчет того, что имеет похожий синтаксис для Enumerable.Empty:
/// <summary>
/// Contains a method used to provide an empty, read-only collection.
/// </summary>
public static class ReadOnlyCollection
{
/// <summary>
/// Returns an empty, read-only collection that has the specified type argument.
/// </summary>
/// <typeparam name="T">
/// The type to assign to the type parameter of the returned generic read-only collection.
/// </typeparam>
/// <returns>
/// An empty, read-only collection whose type argument is T.
/// </returns>
public static IReadOnlyCollection<T> Empty<T>()
{
return CachedValueProvider<T>.Value;
}
/// <summary/>
static class CachedValueProvider<T>
{
/// <summary/>
public static readonly IReadOnlyCollection<T> Value = new T[0];
}
}
Используется следующим образом:
IReadOnlyCollection<int> empty = ReadOnlyCollection.Empty<int>();
Ответ 5
return new List<XElement>().AsReadOnly();