The Labs \ Source Viewer \ SSCLI \ System.Collections.ObjectModel \ Collection

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace System.Collections.ObjectModel
  16. {
  17.     using System;
  18.     using System.Collections;
  19.     using System.Collections.Generic;
  20.     using System.Diagnostics;
  21.    
  22.     [Serializable()]
  23.     [System.Runtime.InteropServices.ComVisible(false)]
  24.     [DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
  25.     [DebuggerDisplay("Count = {Count}")]
  26.     public class Collection<T> : IList<T>, IList
  27.     {
  28.         IList<T> items;
  29.         [NonSerialized()]
  30.         private object _syncRoot;
  31.        
  32.         public Collection()
  33.         {
  34.             items = new List<T>();
  35.         }
  36.        
  37.         public Collection(IList<T> list)
  38.         {
  39.             if (list == null) {
  40.                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.list);
  41.             }
  42.             items = list;
  43.         }
  44.        
  45.         public int Count {
  46.             get { return items.Count; }
  47.         }
  48.        
  49.         protected IList<T> Items {
  50.             get { return items; }
  51.         }
  52.        
  53.         public T this[int index]
  54.         {
  55.             get { return items[index]; }
  56.             set {
  57.                 if (items.IsReadOnly) {
  58.                     ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
  59.                 }
  60.                
  61.                 if (index < 0 || index >= items.Count) {
  62.                     ThrowHelper.ThrowArgumentOutOfRangeException();
  63.                 }
  64.                
  65.                 SetItem(index, value);
  66.             }
  67.         }
  68.        
  69.         public void Add(T item)
  70.         {
  71.             if (items.IsReadOnly) {
  72.                 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
  73.             }
  74.            
  75.             int index = items.Count;
  76.             InsertItem(index, item);
  77.         }
  78.        
  79.         public void Clear()
  80.         {
  81.             if (items.IsReadOnly) {
  82.                 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
  83.             }
  84.            
  85.             ClearItems();
  86.         }
  87.        
  88.         public void CopyTo(T[] array, int index)
  89.         {
  90.             items.CopyTo(array, index);
  91.         }
  92.        
  93.         public bool Contains(T item)
  94.         {
  95.             return items.Contains(item);
  96.         }
  97.        
  98.         public IEnumerator<T> GetEnumerator()
  99.         {
  100.             return items.GetEnumerator();
  101.         }
  102.        
  103.         public int IndexOf(T item)
  104.         {
  105.             return items.IndexOf(item);
  106.         }
  107.        
  108.         public void Insert(int index, T item)
  109.         {
  110.             if (index < 0 || index > items.Count) {
  111.                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_ListInsert);
  112.             }
  113.            
  114.             InsertItem(index, item);
  115.         }
  116.        
  117.         public bool Remove(T item)
  118.         {
  119.             if (items.IsReadOnly) {
  120.                 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
  121.             }
  122.            
  123.             int index = items.IndexOf(item);
  124.             if (index < 0)
  125.                 return false;
  126.             RemoveItem(index);
  127.             return true;
  128.         }
  129.        
  130.         public void RemoveAt(int index)
  131.         {
  132.             if (items.IsReadOnly) {
  133.                 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
  134.             }
  135.            
  136.             if (index < 0 || index >= items.Count) {
  137.                 ThrowHelper.ThrowArgumentOutOfRangeException();
  138.             }
  139.            
  140.             RemoveItem(index);
  141.         }
  142.        
  143.         protected virtual void ClearItems()
  144.         {
  145.             items.Clear();
  146.         }
  147.        
  148.         protected virtual void InsertItem(int index, T item)
  149.         {
  150.             items.Insert(index, item);
  151.         }
  152.        
  153.         protected virtual void RemoveItem(int index)
  154.         {
  155.             items.RemoveAt(index);
  156.         }
  157.        
  158.         protected virtual void SetItem(int index, T item)
  159.         {
  160.             items[index] = item;
  161.         }
  162.        
  163.         bool ICollection<T>.IsReadOnly {
  164.             get { return items.IsReadOnly; }
  165.         }
  166.        
  167.         IEnumerator IEnumerable.GetEnumerator()
  168.         {
  169.             return ((IEnumerable)items).GetEnumerator();
  170.         }
  171.        
  172.         bool ICollection.IsSynchronized {
  173.             get { return false; }
  174.         }
  175.        
  176.         object ICollection.SyncRoot {
  177.             get {
  178.                 if (_syncRoot == null) {
  179.                     ICollection c = items as ICollection;
  180.                     if (c != null) {
  181.                         _syncRoot = c.SyncRoot;
  182.                     }
  183.                     else {
  184.                         System.Threading.Interlocked.CompareExchange(ref _syncRoot, new object(), null);
  185.                     }
  186.                 }
  187.                 return _syncRoot;
  188.             }
  189.         }
  190.        
  191.         void ICollection.CopyTo(Array array, int index)
  192.         {
  193.             if (array == null) {
  194.                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
  195.             }
  196.            
  197.             if (array.Rank != 1) {
  198.                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
  199.             }
  200.            
  201.             if (array.GetLowerBound(0) != 0) {
  202.                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
  203.             }
  204.            
  205.             if (index < 0) {
  206.                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
  207.             }
  208.            
  209.             if (array.Length - index < Count) {
  210.                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
  211.             }
  212.            
  213.             T[] tArray = array as T[];
  214.             if (tArray != null) {
  215.                 items.CopyTo(tArray, index);
  216.             }
  217.             else {
  218.                 //
  219.                 // Catch the obvious case assignment will fail.
  220.                 // We can found all possible problems by doing the check though.
  221.                 // For example, if the element type of the Array is derived from T,
  222.                 // we can't figure out if we can successfully copy the element beforehand.
  223.                 //
  224.                 Type targetType = array.GetType().GetElementType();
  225.                 Type sourceType = typeof(T);
  226.                 if (!(targetType.IsAssignableFrom(sourceType) || sourceType.IsAssignableFrom(targetType))) {
  227.                     ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
  228.                 }
  229.                
  230.                 //
  231.                 // We can't cast array of value type to object[], so we don't support
  232.                 // widening of primitive types here.
  233.                 //
  234.                 object[] objects = array as object[];
  235.                 if (objects == null) {
  236.                     ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
  237.                 }
  238.                
  239.                 int count = items.Count;
  240.                 try {
  241.                     for (int i = 0; i < count; i++) {
  242.                         objects[index++] = items[i];
  243.                     }
  244.                 }
  245.                 catch (ArrayTypeMismatchException) {
  246.                     ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
  247.                 }
  248.             }
  249.         }
  250.        
  251.         object IList.this[int index]
  252.         {
  253.             get { return items[index]; }
  254.             set {
  255.                 VerifyValueType(value);
  256.                 this[index] = (T)value;
  257.             }
  258.         }
  259.        
  260.         bool IList.IsReadOnly {
  261.             get { return items.IsReadOnly; }
  262.         }
  263.        
  264.         bool IList.IsFixedSize {
  265.             get {
  266.                 // There is no IList<T>.IsFixedSize, so we must assume false if our
  267.                 // internal item collection does not implement IList
  268.                 IList list = items as IList;
  269.                 if (list != null) {
  270.                     return list.IsFixedSize;
  271.                 }
  272.                 return false;
  273.             }
  274.         }
  275.        
  276.         int IList.Add(object value)
  277.         {
  278.             if (items.IsReadOnly) {
  279.                 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
  280.             }
  281.            
  282.             VerifyValueType(value);
  283.             Add((T)value);
  284.             return this.Count - 1;
  285.         }
  286.        
  287.         bool IList.Contains(object value)
  288.         {
  289.             if (IsCompatibleObject(value)) {
  290.                 return Contains((T)value);
  291.             }
  292.             return false;
  293.         }
  294.        
  295.         int IList.IndexOf(object value)
  296.         {
  297.             if (IsCompatibleObject(value)) {
  298.                 return IndexOf((T)value);
  299.             }
  300.             return -1;
  301.         }
  302.        
  303.         void IList.Insert(int index, object value)
  304.         {
  305.             if (items.IsReadOnly) {
  306.                 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
  307.             }
  308.            
  309.             VerifyValueType(value);
  310.             Insert(index, (T)value);
  311.         }
  312.        
  313.         void IList.Remove(object value)
  314.         {
  315.             if (items.IsReadOnly) {
  316.                 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
  317.             }
  318.            
  319.             if (IsCompatibleObject(value)) {
  320.                 Remove((T)value);
  321.             }
  322.         }
  323.        
  324.         private static bool IsCompatibleObject(object value)
  325.         {
  326.             if ((value is T) || (value == null && !typeof(T).IsValueType)) {
  327.                 return true;
  328.             }
  329.             return false;
  330.         }
  331.        
  332.         private static void VerifyValueType(object value)
  333.         {
  334.             if (!IsCompatibleObject(value)) {
  335.                 ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T));
  336.             }
  337.         }
  338.     }
  339. }

Developer Fusion