Background and motivation
If someone wants to return an IList<T> via a read-only wrapper that prevents the list from being mutated via that reference, they can wrap it in a ReadOnlyCollection<T>.
If they have an IDictionary<TKey, TValue>, they can wrap it in a ReadOnlyDictionary<TKey, TValue>.
But if they have an ISet<T>, there's no ReadOnlySet<T> that can be used to easily wrap the set. The dev needs to either write their own wrapper type, and will instead often end up making a copy with an ImmutableHashSet<T> or FrozenSet<T>.
Related:
#76028
#29387
#2293
API Proposal
namespace System.Collections.ObjectModel;
[DebuggerDisplay("Count = {Count}")]
public class ReadOnlySet<T> : IReadOnlySet<T>, ISet<T>, ICollection
{
public ReadOnlySet(ISet<T> set);
public static ReadOnlySet<T> Empty { get; }
protected ISet<T> Set { get; }
public int Count { get; }
public IEnumerator<T> GetEnumerator();
public bool Contains(T item);
public bool IsProperSubsetOf(IEnumerable<T> other);
public bool IsProperSupersetOf(IEnumerable<T> other);
public bool IsSubsetOf(IEnumerable<T> other);
public bool IsSupersetOf(IEnumerable<T> other);
public bool Overlaps(IEnumerable<T> other);
public bool SetEquals(IEnumerable<T> other);
... // explicit interface implementations of all other interface methods, throwing from mutating members
}
API Usage
HashSet<int> set = ...;
var ros = new ReadOnlySet<int>(set);
Alternative Designs
ISet<T> exposes CopyTo while IReadOnlySet<T> does not. ReadOnlySet<T> will implement it, but should it be implicit or explicitly implemented? (Alternatively/separately, should we consider adding CopyTo to IReadOnlyCollection<T> and thus implicitly to IReadOnlySet<T>?)
- Do we also want an
ReadOnlySet<T> AsReadOnly() on HashSet<T>? List<T> has ReadOnlyCollection<T> AsReadOnly() and there's a static ReadOnlyCollection<T> AsReadOnly(T[]) on Array, but Dictionary<> doesn't have an AsReadOnly.
- Do we also want an extension method
ReadOnlySet<T> AsReadOnly(this ISet<T>)? Such an extension exists for both IList<T> and IDictionary<>.
- What reference assembly should this be exposed from? ReadOnlyCollection/Dictionary are both implemented in CoreLib and exposed via System.Runtime. Should this live there, too? Or in System.Collections.dll?
Risks
n/a
Background and motivation
If someone wants to return an
IList<T>via a read-only wrapper that prevents the list from being mutated via that reference, they can wrap it in aReadOnlyCollection<T>.If they have an
IDictionary<TKey, TValue>, they can wrap it in aReadOnlyDictionary<TKey, TValue>.But if they have an
ISet<T>, there's noReadOnlySet<T>that can be used to easily wrap the set. The dev needs to either write their own wrapper type, and will instead often end up making a copy with anImmutableHashSet<T>orFrozenSet<T>.Related:
#76028
#29387
#2293
API Proposal
API Usage
Alternative Designs
ISet<T>exposesCopyTowhileIReadOnlySet<T>does not.ReadOnlySet<T>will implement it, but should it be implicit or explicitly implemented? (Alternatively/separately, should we consider addingCopyTotoIReadOnlyCollection<T>and thus implicitly toIReadOnlySet<T>?)ReadOnlySet<T> AsReadOnly()onHashSet<T>?List<T>hasReadOnlyCollection<T> AsReadOnly()and there's astatic ReadOnlyCollection<T> AsReadOnly(T[])onArray, butDictionary<>doesn't have anAsReadOnly.ReadOnlySet<T> AsReadOnly(this ISet<T>)? Such an extension exists for bothIList<T>andIDictionary<>.Risks
n/a