Как создать пустой IReadOnlyCollection
Я создал метод расширения для MultiValueDictionary для инкапсуляции часто ContainsKey
проверяет, и мне было интересно, что лучший способ создать пустой IReadOnlyCollection
?.
то, что я использовал до сих пор, это new List<TValue>(0).AsReadOnly()
но должен быть лучший способ, равноценный IEnumerable
' s 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;
}
4 ответов
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>();
Я не думаю, что есть что-то вроде Enumerable.Empty
для коллекций только для чтения, но:
List<T>
уже реализуетIReadOnlyCollection<T>
таким образом, вы можете избежать выделения одного объекта, не вызываяAsReadOnly()
и просто вместо формы списка. Это менее "безопасно" в теории, но вряд ли имеет значение на практике.кроме того, вы можете кэшировать возвращенную коллекцию ReadOnlyCollection, чтобы избежать любого выделения объекта вообще (за исключением кэшированного объект.)
насколько я знаю, нет встроенного способа (интересно узнать, есть ли он). Тем не менее, вы можете использовать следующее:
IReadOnlyCollection<TValue> readonlyCollection = new ReadOnlyCollection<TValue>(new TValue[] { });
дополнительно вы можете кэшировать результаты, так как это ReadOnlyCollection
над пустым массивом он всегда будет одинаковым независимо от того, сколько экземпляров у вас есть.
Как насчет этого, который имеет аналогичный синтаксис для Enumerable.Пусто:
/// <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>();