Merge pull request #620 from knocte/monoservice_playground
[mono.git] / mcs / class / corlib / System.Collections.ObjectModel / Collection.cs
1 // -*- Mode: csharp; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2 //
3 // System.Collections.ObjectModel.Collection
4 //
5 // Authors:
6 //    Zoltan Varga (vargaz@gmail.com)
7 //    David Waite (mass@akuma.org)
8 //    Marek Safar (marek.safar@gmail.com)
9 //
10 // (C) 2005 Novell, Inc.
11 // (C) 2005 David Waite
12 //
13
14 //
15 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
16 // Copyright (C) 2005 David Waite
17 // Copyright (C) 2011 Xamarin, Inc (http://www.xamarin.com)
18 //
19 // Permission is hereby granted, free of charge, to any person obtaining
20 // a copy of this software and associated documentation files (the
21 // "Software"), to deal in the Software without restriction, including
22 // without limitation the rights to use, copy, modify, merge, publish,
23 // distribute, sublicense, and/or sell copies of the Software, and to
24 // permit persons to whom the Software is furnished to do so, subject to
25 // the following conditions:
26 // 
27 // The above copyright notice and this permission notice shall be
28 // included in all copies or substantial portions of the Software.
29 // 
30 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
31 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
33 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
34 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
35 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
36 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 //
38
39 using System;
40 using System.Collections;
41 using System.Collections.Generic;
42 using System.Runtime.InteropServices;
43 using System.Diagnostics;
44
45 namespace System.Collections.ObjectModel
46 {
47         [ComVisible (false)]
48         [Serializable]
49         [DebuggerDisplay ("Count={Count}")]
50         [DebuggerTypeProxy (typeof (CollectionDebuggerView<>))]
51         public class Collection<T> : IList<T>, IList
52 #if NET_4_5
53                 , IReadOnlyList<T>
54 #endif
55         {
56                 IList <T> items;
57                 [field:NonSerializedAttribute()]
58                 object syncRoot;
59                 
60                 public Collection ()
61                 {
62                         List <T> l = new List <T> ();
63                         IList l2 = l as IList;
64                         syncRoot = l2.SyncRoot;
65                         items = l;
66                 }
67
68                 public Collection (IList <T> items)
69                 {
70                         if (items == null)
71                                 throw new ArgumentNullException ("items");
72                         this.items = items;
73                         ICollection l = items as ICollection;
74                         syncRoot = (l != null) ? l.SyncRoot : new object ();
75                 }
76
77                 public void Add (T item)
78                 {
79                         int idx = items.Count;
80                         InsertItem (idx, item);
81                 }
82
83                 public void Clear ()
84                 {
85                         ClearItems ();
86                 }
87
88                 protected virtual void ClearItems ()
89                 {
90                         items.Clear ();
91                 }
92
93                 public bool Contains (T item)
94                 {
95                         return items.Contains (item);
96                 }
97
98                 public void CopyTo (T [] array, int index)
99                 {
100                         items.CopyTo (array, index);
101                 }
102
103                 public IEnumerator <T> GetEnumerator ()
104                 {
105                         return items.GetEnumerator ();
106                 }
107
108                 public int IndexOf (T item)
109                 {
110                         return items.IndexOf (item);
111                 }
112
113                 public void Insert (int index, T item)
114                 {
115                         InsertItem (index, item);
116                 }
117
118                 protected virtual void InsertItem (int index, T item)
119                 {
120                         items.Insert (index, item);
121                 }
122
123                 protected IList<T> Items {
124                         get { return items; }
125                 }
126
127                 public bool Remove (T item)
128                 {
129                         int idx = IndexOf (item);
130                         if (idx == -1) 
131                                 return false;
132                         
133                         RemoveItem (idx);
134                         
135                         return true;
136                 }
137
138                 public void RemoveAt (int index)
139                 {
140                         RemoveItem (index);
141                 }
142
143                 protected virtual void RemoveItem (int index)
144                 {
145                         items.RemoveAt (index);
146                 }
147
148                 public int Count {
149                         get { return items.Count; }
150                 }
151
152                 public T this [int index] {
153                         get { return items [index]; }
154                         set { SetItem (index, value); }
155                 }
156
157                 bool ICollection<T>.IsReadOnly {
158                         get { return items.IsReadOnly; }
159                 }
160
161                 protected virtual void SetItem (int index, T item)
162                 {
163                         items[index] = item;
164                 }
165
166                 
167 #region Helper methods for non-generic interfaces
168                 
169                 internal static T ConvertItem (object item)
170                 {
171                         if (CollectionHelpers.IsValidItem<T> (item))
172                                 return (T)item;
173                         throw new ArgumentException ("item");
174                 }
175                 
176                 internal static void CheckWritable (IList <T> items)
177                 {
178                         if (items.IsReadOnly)
179                                 throw new NotSupportedException ();
180                 }
181                 
182                 internal static bool IsSynchronized (IList <T> items)
183                 {
184                         ICollection c = items as ICollection;
185                         return (c != null) ? c.IsSynchronized : false;
186                 }
187                 
188                 internal static bool IsFixedSize (IList <T> items)
189                 {
190                         IList l = items as IList;
191                         return (l != null) ? l.IsFixedSize : false;
192                 }
193 #endregion
194
195 #region Not generic interface implementations
196                 void ICollection.CopyTo (Array array, int index)
197                 {
198                         ((ICollection)items).CopyTo (array, index);
199                 }
200                 
201                 IEnumerator IEnumerable.GetEnumerator ()
202                 {
203                         return (IEnumerator) items.GetEnumerator ();
204                 }
205                                 
206                 int IList.Add (object value)
207                 {
208                         int idx = items.Count;
209                         InsertItem (idx, ConvertItem (value));
210                         return idx;
211                 }
212                 
213                 bool IList.Contains (object value)
214                 {
215                         if (CollectionHelpers.IsValidItem<T> (value))
216                                 return items.Contains ((T) value);
217                         return false;
218                 }
219                 
220                 int IList.IndexOf (object value)
221                 {
222                         if (CollectionHelpers.IsValidItem<T> (value))
223                                 return items.IndexOf ((T) value);
224                         return -1;
225                 }
226                 
227                 void IList.Insert (int index, object value)
228                 {
229                         InsertItem (index, ConvertItem (value));
230                 }
231                 
232                 void IList.Remove (object value)
233                 {
234                         CheckWritable (items);
235
236                         int idx = IndexOf (ConvertItem (value));
237
238                         RemoveItem (idx);
239                 }
240                 
241                 bool ICollection.IsSynchronized {
242                         get { return IsSynchronized (items); }
243                 }
244                 
245                 object ICollection.SyncRoot {
246                         get { return syncRoot; }
247                 }
248                 bool IList.IsFixedSize {
249                         get { return IsFixedSize (items); }
250                 }
251                 
252                 bool IList.IsReadOnly {
253                         get { return items.IsReadOnly; }
254                 }
255                 
256                 object IList.this [int index] {
257                         get { return items [index]; }
258                         set { SetItem (index, ConvertItem (value)); }
259                 }
260 #endregion
261         }
262
263         static class CollectionHelpers
264         {
265                 public static bool IsValidItem<T> (object item)
266                 {
267                         return item is T || (item == null && ! typeof (T).IsValueType);
268                 }
269         }
270 }