2011-05-12 1 views
4

내가 생각하기에, IEnumerable 것들은 반복 할 수있는 객체입니다.
또한 ICollection 인 경우 얼마나 많은 요소가 있는지 알 수 있습니다.
그리고 심지어 IList이라면 특정 인덱스의 오브젝트를 포함 할 수 있습니다.ReadOnlyCollection <T>이 ReadOnlyList가 아닌 이유 <T>?

ReadOnlyCollection<T>IList<T>을 구현합니다. 그래서 wouldnt ReadOnlyList<T> 더 좋은 이름이 될.

프레임 워크에 실제 ReadOnlyCollection<T>이 있습니까?
ReadOnlyCollection<T>으로

+0

명명 물건 "은 IList의"를 다시 어렵다 ... 그리고 - 그냥 당신이 원하는 항목의 배열을 제공합니다 ... 당신이 필요 * 어떻게 든 *에 객체 무엇을 이야기합니다 –

+0

을 포함하십시오. nt IEnumerable + IList/ICollection에서 계산하지만 IList의 항목이 아닙니다. – Rup

+0

@Rup : 예, 읽을 수있는 ICollection을 노출해야합니다. – ordag

답변

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

,을 위해 유사한 래퍼를 생성하는 것은 매우 쉬워야한다 단순히 목록을 수정 허용하지 IList<T>에 대한 래퍼입니다 (그래서는 읽기 전용 랩퍼를 작성하는은 IList 필요 없어요) 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; 
     } 
    } 
} 
+0

... (generic이 아닌)'ICollection'을 구현해야한다면 더 복잡해집니다. – ordag

+0

감사합니다. 그러나 :'ICollection '은'ICollection'을 구현할 필요는 없습니다. 그래서 CopyTo (Array, int)는 항상 작동하지 않을 것이다. – ordag

+0

@ordag : 위의 예제에서 필요없는 코드를 제거하기 만하면된다. 적절한 읽기 전용 래퍼를 만드는 것은 너무 어렵지 않아야한다; –

관련 문제