diff options
Diffstat (limited to 'src/mscorlib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs')
-rw-r--r-- | src/mscorlib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/src/mscorlib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs b/src/mscorlib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs new file mode 100644 index 0000000000..f1d2a0969b --- /dev/null +++ b/src/mscorlib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs @@ -0,0 +1,279 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.Diagnostics; + +namespace System.Collections.ObjectModel +{ + [Serializable] + [DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))] + [DebuggerDisplay("Count = {Count}")] + [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + public class ReadOnlyCollection<T> : IList<T>, IList, IReadOnlyList<T> + { + private IList<T> list; // Do not rename (binary serialization) + [NonSerialized] + private Object _syncRoot; + + public ReadOnlyCollection(IList<T> list) + { + if (list == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.list); + } + this.list = list; + } + + public int Count + { + get { return list.Count; } + } + + public T this[int index] + { + get { return list[index]; } + } + + public bool Contains(T value) + { + return list.Contains(value); + } + + public void CopyTo(T[] array, int index) + { + list.CopyTo(array, index); + } + + public IEnumerator<T> GetEnumerator() + { + return list.GetEnumerator(); + } + + public int IndexOf(T value) + { + return list.IndexOf(value); + } + + protected IList<T> Items + { + get + { + return list; + } + } + + bool ICollection<T>.IsReadOnly + { + get { return true; } + } + + T IList<T>.this[int index] + { + get { return list[index]; } + set + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + } + + void ICollection<T>.Add(T value) + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + + void ICollection<T>.Clear() + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + + void IList<T>.Insert(int index, T value) + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + + bool ICollection<T>.Remove(T value) + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + return false; + } + + void IList<T>.RemoveAt(int index) + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)list).GetEnumerator(); + } + + bool ICollection.IsSynchronized + { + get { return false; } + } + + object ICollection.SyncRoot + { + get + { + if (_syncRoot == null) + { + ICollection c = list as ICollection; + if (c != null) + { + _syncRoot = c.SyncRoot; + } + else + { + System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null); + } + } + return _syncRoot; + } + } + + void ICollection.CopyTo(Array array, int index) + { + if (array == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + } + + if (array.Rank != 1) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); + } + + if (array.GetLowerBound(0) != 0) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound); + } + + if (index < 0) + { + ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); + } + + if (array.Length - index < Count) + { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); + } + + T[] items = array as T[]; + if (items != null) + { + list.CopyTo(items, index); + } + else + { + // + // Catch the obvious case assignment will fail. + // We can't find all possible problems by doing the check though. + // For example, if the element type of the Array is derived from T, + // we can't figure out if we can successfully copy the element beforehand. + // + Type targetType = array.GetType().GetElementType(); + Type sourceType = typeof(T); + if (!(targetType.IsAssignableFrom(sourceType) || sourceType.IsAssignableFrom(targetType))) + { + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); + } + + // + // We can't cast array of value type to object[], so we don't support + // widening of primitive types here. + // + object[] objects = array as object[]; + if (objects == null) + { + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); + } + + int count = list.Count; + try + { + for (int i = 0; i < count; i++) + { + objects[index++] = list[i]; + } + } + catch (ArrayTypeMismatchException) + { + ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); + } + } + } + + bool IList.IsFixedSize + { + get { return true; } + } + + bool IList.IsReadOnly + { + get { return true; } + } + + object IList.this[int index] + { + get { return list[index]; } + set + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + } + + int IList.Add(object value) + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + return -1; + } + + void IList.Clear() + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + + private static bool IsCompatibleObject(object value) + { + // Non-null values are fine. Only accept nulls if T is a class or Nullable<U>. + // Note that default(T) is not equal to null for value types except when T is Nullable<U>. + return ((value is T) || (value == null && default(T) == null)); + } + + bool IList.Contains(object value) + { + if (IsCompatibleObject(value)) + { + return Contains((T)value); + } + return false; + } + + int IList.IndexOf(object value) + { + if (IsCompatibleObject(value)) + { + return IndexOf((T)value); + } + return -1; + } + + void IList.Insert(int index, object value) + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + + void IList.Remove(object value) + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + + void IList.RemoveAt(int index) + { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + } +} |