为什么ReadOnlyCollection <t>不是ReadOnlyList <t>?</t> </t>

时间:2011-05-12 10:40:24

标签: .net collections readonly

我认为IEnumerable事物是你可以迭代的对象 如果他们也是ICollection你知道那里有多少元素。
如果它们是偶数IList,您可以从特定索引中包含对象。

ReadOnlyCollection<T>实施IList<T>。所以ReadOnlyList<T>不是一个更好的名字。

框架中是否有真正的ReadOnlyCollection<T>
(所以我不需要IList来创建这样的只读包装器)

2 个答案:

答案 0 :(得分:0)

由于ReadOnlyCollection<T>只是IList<T>不允许修改列表的包装器,因此为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;
        }
    }
}

答案 1 :(得分:0)

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;
            }
        }
    }
}