diff options
author | Jiyoung Yun <jy910.yun@samsung.com> | 2016-11-23 19:09:09 +0900 |
---|---|---|
committer | Jiyoung Yun <jy910.yun@samsung.com> | 2016-11-23 19:09:09 +0900 |
commit | 4b4aad7217d3292650e77eec2cf4c198ea9c3b4b (patch) | |
tree | 98110734c91668dfdbb126fcc0e15ddbd93738ca /src/mscorlib/src/System/Collections/ObjectModel/Collection.cs | |
parent | fa45f57ed55137c75ac870356a1b8f76c84b229c (diff) | |
download | coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.gz coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.bz2 coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.zip |
Imported Upstream version 1.1.0upstream/1.1.0
Diffstat (limited to 'src/mscorlib/src/System/Collections/ObjectModel/Collection.cs')
-rw-r--r-- | src/mscorlib/src/System/Collections/ObjectModel/Collection.cs | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Collections/ObjectModel/Collection.cs b/src/mscorlib/src/System/Collections/ObjectModel/Collection.cs new file mode 100644 index 0000000000..54aa7bb09d --- /dev/null +++ b/src/mscorlib/src/System/Collections/ObjectModel/Collection.cs @@ -0,0 +1,328 @@ +// 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. + +// + +namespace System.Collections.ObjectModel +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Diagnostics; + using System.Runtime; + + [Serializable] + [System.Runtime.InteropServices.ComVisible(false)] + [DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))] + [DebuggerDisplay("Count = {Count}")] + public class Collection<T>: IList<T>, IList, IReadOnlyList<T> + { + IList<T> items; + [NonSerialized] + private Object _syncRoot; + + public Collection() { + items = new List<T>(); + } + + public Collection(IList<T> list) { + if (list == null) { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.list); + } + items = list; + } + + public int Count { + get { return items.Count; } + } + + protected IList<T> Items { + get { return items; } + } + + public T this[int index] { + get { return items[index]; } + set { + if( items.IsReadOnly) { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + + if (index < 0 || index >= items.Count) { + ThrowHelper.ThrowArgumentOutOfRange_IndexException(); + } + + SetItem(index, value); + } + } + + public void Add(T item) { + if( items.IsReadOnly) { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + + int index = items.Count; + InsertItem(index, item); + } + + public void Clear() { + if( items.IsReadOnly) { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + + ClearItems(); + } + + public void CopyTo(T[] array, int index) { + items.CopyTo(array, index); + } + + public bool Contains(T item) { + return items.Contains(item); + } + + public IEnumerator<T> GetEnumerator() { + return items.GetEnumerator(); + } + + public int IndexOf(T item) { + return items.IndexOf(item); + } + + public void Insert(int index, T item) { + if (items.IsReadOnly) { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + + if (index < 0 || index > items.Count) { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_ListInsert); + } + + InsertItem(index, item); + } + + public bool Remove(T item) { + if( items.IsReadOnly) { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + + int index = items.IndexOf(item); + if (index < 0) return false; + RemoveItem(index); + return true; + } + + public void RemoveAt(int index) { + if( items.IsReadOnly) { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + + if (index < 0 || index >= items.Count) { + ThrowHelper.ThrowArgumentOutOfRange_IndexException(); + } + + RemoveItem(index); + } + + protected virtual void ClearItems() { + items.Clear(); + } + + protected virtual void InsertItem(int index, T item) { + items.Insert(index, item); + } + + protected virtual void RemoveItem(int index) { + items.RemoveAt(index); + } + + protected virtual void SetItem(int index, T item) { + items[index] = item; + } + + bool ICollection<T>.IsReadOnly { + get { + return items.IsReadOnly; + } + } + + IEnumerator IEnumerable.GetEnumerator() { + return ((IEnumerable)items).GetEnumerator(); + } + + bool ICollection.IsSynchronized { + get { return false; } + } + + object ICollection.SyncRoot { + get { + if( _syncRoot == null) { + ICollection c = items 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.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); + } + + if (array.Length - index < Count) { + ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); + } + + T[] tArray = array as T[]; + if (tArray != null) { + items.CopyTo(tArray , index); + } + else { + // + // Catch the obvious case assignment will fail. + // We can found 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(ExceptionResource.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(ExceptionResource.Argument_InvalidArrayType); + } + + int count = items.Count; + try { + for (int i = 0; i < count; i++) { + objects[index++] = items[i]; + } + } + catch(ArrayTypeMismatchException) { + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType); + } + } + } + + object IList.this[int index] { + get { return items[index]; } + set { + ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value); + + try { + this[index] = (T)value; + } + catch (InvalidCastException) { + ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T)); + } + + } + } + + bool IList.IsReadOnly { + get { + return items.IsReadOnly; + } + } + + bool IList.IsFixedSize { + get { + // There is no IList<T>.IsFixedSize, so we must assume that only + // readonly collections are fixed size, if our internal item + // collection does not implement IList. Note that Array implements + // IList, and therefore T[] and U[] will be fixed-size. + IList list = items as IList; + if(list != null) + { + return list.IsFixedSize; + } + return items.IsReadOnly; + } + } + + int IList.Add(object value) { + if( items.IsReadOnly) { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value); + + try { + Add((T)value); + } + catch (InvalidCastException) { + ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T)); + } + + return this.Count - 1; + } + + 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) { + if( items.IsReadOnly) { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value); + + try { + Insert(index, (T)value); + } + catch (InvalidCastException) { + ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T)); + } + + } + + void IList.Remove(object value) { + if( items.IsReadOnly) { + ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); + } + + if(IsCompatibleObject(value)) { + Remove((T) value); + } + } + + 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)); + } + } +} |