开发者

Why is the ReadOnlyCollection<T> not a ReadOnlyList<T>?

I thought IEnumerable things are objects over which you can iterate.

If they are also ICollections you know how much elements are in there.

And if they are even ILists you can take containing objects from a开发者_如何学Go specific index.

A ReadOnlyCollection<T> implements IList<T>. So wouldnt ReadOnlyList<T> be a better name.

And is there a real ReadOnlyCollection<T> in the framework?

(So I dont need an IList to create such a read only wrapper)


As ReadOnlyCollection<T> is simply a wrapper for an IList<T> that disallows modifying the list, it should be very easy to generate a similar wrapper for an ICollection<T>:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;

class MyReadOnlyCollection<T> : ICollection<T>, IEnumerable<T>, ICollection, IEnumerable
{
    private ICollection<T> _collection;
    private object _syncRoot;

    public MyReadOnlyCollection(ICollection<T> collection)
    {
        _collection = collection;
    }


    public void Add(T item)
    {
        throw new NotSupportedException("Trying to modify a read-only collection.");
    }

    public void Clear()
    {
        throw new NotSupportedException("Trying to modify a read-only collection.");
    }

    public bool Contains(T item)
    {
        return _collection.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        _collection.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return _collection.Count; }
    }

    public bool IsReadOnly
    {
        get { return true; }
    }

    public bool Remove(T item)
    {
        throw new NotSupportedException("Trying to modify a read-only collection.");
    }

    public IEnumerator<T> GetEnumerator()
    {
        return _collection.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return ((ICollection)_collection).GetEnumerator();
    }

    public void CopyTo(Array array, int index)
    {
        ((ICollection)_collection).CopyTo(array, index);
    }

    public bool IsSynchronized
    {
        get { return false; }
    }

    public object SyncRoot
    {
        get
        {
            if (_syncRoot == null)
            {
                ICollection list = _collection as ICollection;
                if (list != null)
                {
                    _syncRoot = list.SyncRoot;
                }
                else
                {
                    Interlocked.CompareExchange(ref _syncRoot, new object(), null);
                }
            }
            return _syncRoot;
        }
    }
}


namespace System.Collections.ObjectModel
{
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Threading;

    internal sealed class CollectionDebugView<T>
    {
        private readonly ICollection<T> collection;

        public CollectionDebugView(ICollection<T> collection)
        {
            if (collection == null) { throw new ArgumentNullException("collection"); }

            this.collection = collection;
        }

        [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
        public T[] Items
        {
            get
            {
                T[] items = new T[this.collection.Count];
                this.collection.CopyTo(items, 0);
                return items;
            }
        }
    }

    [Serializable]
    [ComVisible(false)]
    [DebuggerDisplay("Count = {Count}")]
    [DebuggerTypeProxy(typeof(CollectionDebugView<>))]
    public class ReadOnlyCollection<T> : ICollection<T>, ICollection
    {
        private readonly ICollection<T> genericCollection;
        private readonly ICollection nongenericCollection;

        [NonSerialized]
        private object syncRoot;

        public ReadOnlyCollection(ICollection<T> collection)
        {
            if (collection == null) { throw new ArgumentNullException("collection"); }

            this.genericCollection = collection;
            this.nongenericCollection = collection as ICollection;
        }

        void ICollection<T>.Add(T item)
        {
            throw new NotSupportedException();
        }

        void ICollection<T>.Clear()
        {
            throw new NotSupportedException();
        }

        public bool Contains(T item)
        {
            return this.genericCollection.Contains(item);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            this.genericCollection.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return this.genericCollection.Count; }
        }

        public bool IsReadOnly
        {
            get { return true; }
        }

        bool ICollection<T>.Remove(T item)
        {
            throw new NotSupportedException();
        }

        public IEnumerator<T> GetEnumerator()
        {
            return this.genericCollection.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IEnumerable)this.genericCollection).GetEnumerator();
        }

        void ICollection.CopyTo(Array array, int index)
        {
            if (this.nongenericCollection == null)
            {
                if (array == null) { throw new ArgumentNullException("array"); }
                if (array.Rank != 1) { throw new ArgumentException(); }
                if (array.GetLowerBound(0) != 0) { throw new ArgumentException(); }
                if (index < 0) { throw new ArgumentOutOfRangeException(); }
                if (array.Length < index + this.genericCollection.Count) { throw new ArgumentException(); }

                T[] typedArray = array as T[];

                if (typedArray == null)
                {
                    Type arrayType = array.GetType().GetElementType();
                    Type collectionType = typeof(T);

                    if (arrayType.IsAssignableFrom(collectionType) || collectionType.IsAssignableFrom(arrayType))
                    {
                        object[] objectArray = array as object[];

                        if (objectArray == null) { throw new ArgumentException(); }

                        try
                        {
                            foreach (T item in this.genericCollection)
                            {
                                objectArray[index] = item;
                                index++;
                            }
                        }
                        catch (ArrayTypeMismatchException)
                        {
                            throw new ArgumentException();
                        }

                    }
                    else
                    {
                        throw new ArgumentException();
                    }
                }
                else
                {
                    this.genericCollection.CopyTo(typedArray, index);
                }
            }
            else
            {
                this.nongenericCollection.CopyTo(array, index);
            }
        }

        int ICollection.Count
        {
            get { return this.nongenericCollection == null ? this.genericCollection.Count : this.nongenericCollection.Count; }
        }

        bool ICollection.IsSynchronized
        {
            get { return this.nongenericCollection == null ? false : this.nongenericCollection.IsSynchronized; }
        }

        object ICollection.SyncRoot
        {
            get
            {
                if (this.syncRoot == null)
                {
                    if (this.nongenericCollection == null)
                    {
                        this.syncRoot = this.nongenericCollection.SyncRoot;
                    }
                    else
                    {
                        Interlocked.CompareExchange<object>(ref this.syncRoot, new object(), null);
                    }
                }

                return this.syncRoot;
            }
        }
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜