19

我正在为MultiValueDictionary创建一个扩展方法来封装频繁ContainsKey检查,我想知道创建空的最佳方法是什么IReadOnlyCollection

到目前为止我使用的是new List<TValue>(0).AsReadOnly(),但必须有更好的方法,相当于IEnumerable'sEnumerable.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

5 回答 5

31

编辑:新的 .Net 4.6 添加了一个 API 来获取一个空数组:Array.Empty<T>并且数组实现IReadOnlyCollection<T>. 这也减少了分配,因为它只创建一次实例:

IReadOnlyCollection<int> emptyReadOnlyCollection = Array.Empty<int>();

我最终做的是模仿Enumerable.Emptyusing的实现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>();
于 2014-11-21T14:53:22.627 回答
4

据我所知,没有内置方式(有兴趣知道是否有)。也就是说,您可以使用以下内容:

IReadOnlyCollection<TValue> readonlyCollection = new ReadOnlyCollection<TValue>(new TValue[] { });

或者,您可以缓存结果,因为它是一个ReadOnlyCollection过空的数组,无论您有多少实例,它总是相同的。

于 2014-08-10T09:56:40.023 回答
3

Enumerable.Empty我认为只读集合没有类似的东西,但是:

  • List<T>已经实现,因此您可以通过不调用并简单地转换列表来IReadOnlyCollection<T>避免一个对象分配。AsReadOnly()这在理论上不太“安全”,但在实践中几乎不重要。

  • 或者,您可以缓存返回的 ReadOnlyCollection 以避免任何对象分配(缓存对象除外)。

于 2014-08-10T09:56:28.770 回答
3

return new List<XElement>().AsReadOnly();

于 2019-09-28T16:10:28.943 回答
2

与 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>();
于 2014-11-21T14:30:07.633 回答