Skip to content

[API Proposal]: ReadOnly empty collection singletons #76028

Closed
@stephentoub

Description

@stephentoub

Background and motivation

Various pieces of code today allocate new read-only collections (e.g. ReadOnlyCollection<T>) around empty collections. Sometimes code implements its own singleton caching, e.g.

and sometimes it doesn't, e.g.

In other cases, empty could be special-cased but isn't as doing so would have required someone to add their own cache for it to have meaningful benefits).

In any case, we can make this easier and more efficient by exposing our own singletons that we and others can use.

(Replaces #41147, which is limited to just ReadOnlyCollection.)
(Related to #38340, which asked for such Empty methods on mutable collections like List<T> returning empty instances of those same collections. There we said we'd consider read-only variants with a proposal; this is that proposal.)

API Proposal

namespace System.Collections.Generic
{
    public interface IReadOnlyCollection<out T>
    {
+        public static IReadOnlyCollection<T> Empty { get; }
    }

    public interface IReadOnlyList<out T> : IReadOnlyCollection<T>
    {
+        public static new IReadOnlyList<T> Empty { get; }
    }

    public interface IReadOnlyDictionary<TKey, TValue> : IReadOnlyCollection<KeyValuePair<TKey, TValue>>
    {
+        public static new IReadOnlyDictionary<TKey, TValue> Empty { get; }
    }

    public interface IReadOnlySet<T> : IReadOnlyCollection<T>
    {
+        public static new IReadOnlySet<T> Empty { get; }
    }
}

namespace System.Collections.ObjectModel
{
    public class ReadOnlyCollection<T>
    {
+        public static ReadOnlyCollection<T> Empty { get; }
    }

    public class ReadOnlyDictionary<TKey, TValue>
    {
+        public static ReadOnlyDictionary<TKey, TValue> Empty { get; }
    }

    public class ReadOnlyObservableCollection<T>
    {
+        public static ReadOnlyObservableCollection<T> Empty { get; }
    }
}

API Usage

public ReadOnlyCollection<T> GetValues() =>
    _count != 0 ? new ReadOnlyCollection<T>(_values) : ReadOnlyCollection<T>.Empty;

Alternative Designs

No response

Risks

  • These might be our first non-abstract/virtual static interface methods in the core libraries?

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions