Search code examples
c#.netcollectionsienumerablereadonly-collection

Return an ICollection<T> as IReadOnlyCollection<T>?


I have a field of type ICollection<T>. Is there a simple way to make it read only?

Note, the ReadOnlyCollection<T> class takes an IList<T>, I'm looking for a way to invert an ICollection<T> and ensure user cannot alter the collection.

Using AsEnumerable ex. method, won't guarantee that, since it could be casted back to its original type, which could also be List.


Solution

  • I've always thought it a little odd that ReadOnlyCollection<T> is really a read-only list.

    That said, ICollection<T> is such a simple interface, it's trivial to implement a true ReadOnlyCollection<T>:

    public class TrueReadOnlyCollection<T> : ICollection<T>, IReadOnlyCollection<T>
    {
        private ICollection<T> _original;
    
        public TrueReadOnlyCollection(ICollection<T> original)
        {
            _original = original;
        }
    
        public void Add(T item)
        {
            throw new NotSupportedException();
        }
    
        public void Clear()
        {
            throw new NotSupportedException();
        }
    
        public bool Contains(T item)
        {
            return _original.Contains(item);
        }
    
        public void CopyTo(T[] array, int arrayIndex)
        {
            _original.CopyTo(array, arrayIndex);
        }
    
        public int Count
        {
            get { return _original.Count; }
        }
    
        public bool IsReadOnly
        {
            get { return true; }
        }
    
        public bool Remove(T item)
        {
            throw new NotSupportedException();
        }
    
        public IEnumerator<T> GetEnumerator()
        {
            foreach (T t in _original)
            {
                yield return t;
            }
        }
    
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
    

    Note that with .NET 4.5 there are also actual read-only interfaces to support the newish interface-variance features, so if you're doing the above it might be nice to also implement IReadOnlyCollection<T>