Why is the ReadOnlyCollection<T> not a ReadOnlyList<T>?
I thought IEnumerable
things are objects over which you can iterate.
ICollection
s you know how much elements are in there.
And if they are even IList
s 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?
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;
}
}
}
}
精彩评论