我正在为 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;
}
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>();
return new List<XElement>().AsReadOnly();
我不认为有像
Enumerable.Empty
这样的只读集合,但是:
List<T>
已经实现了 IReadOnlyCollection<T>
,因此您可以通过不调用 AsReadOnly()
并简单地转换列表来避免一次对象分配。这在理论上不太“安全”,但在实践中几乎不重要。或者,您可以缓存返回的 ReadOnlyCollection 以避免任何对象分配(缓存的对象除外)。
据我所知,没有内置的方法(有兴趣知道是否有)。也就是说,您可以使用以下内容:
IReadOnlyCollection<TValue> readonlyCollection = new ReadOnlyCollection<TValue>(new TValue[] { });
您可以选择缓存结果,因为它是空数组上的
ReadOnlyCollection
,无论您有多少个实例,它总是相同的。
这个与 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>();
现在,使用.NET8.0我们可以通过以下方式实现:
return ReadOnlyCollection<T>.Empty;