Added tests for Task.WhenAll w/ empty list
[mono.git] / mcs / class / corlib / System.Collections / CollectionBase.cs
1 //
2 // System.Collections.CollectionBase.cs
3 //
4 // Author:
5 //   Nick Drochak II (ndrochak@gol.com)
6 //
7 // (C) 2001 Nick Drochak II
8 //
9
10 //
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System;
34 using System.Runtime.InteropServices;
35
36 namespace System.Collections {
37
38         [ComVisible(true)]
39         [Serializable]
40 #if INSIDE_CORLIB
41         public
42 #else
43         internal
44 #endif
45         abstract class CollectionBase : IList, ICollection, IEnumerable {
46
47                 // private instance properties
48                 private ArrayList list;
49                 
50                 // public instance properties
51                 public int Count { get { return InnerList.Count; } }
52                 
53                 // Public Instance Methods
54                 public IEnumerator GetEnumerator() { return InnerList.GetEnumerator(); }
55                 public void Clear() { 
56                         OnClear();
57                         InnerList.Clear(); 
58                         OnClearComplete();
59                 }
60                 public void RemoveAt (int index) {
61                         object objectToRemove;
62                         objectToRemove = InnerList[index];
63                         OnValidate(objectToRemove);
64                         OnRemove(index, objectToRemove);
65                         InnerList.RemoveAt(index);
66                         OnRemoveComplete(index, objectToRemove);
67                 }
68                 
69                 // Protected Instance Constructors
70                 protected CollectionBase()
71                 { 
72                 }
73
74                 protected CollectionBase (int capacity)
75                 {
76                         list = new ArrayList (capacity);
77                 }
78
79                 [ComVisible (false)]
80                 public int Capacity {
81                         get {
82                                 if (list == null)
83                                         list = new ArrayList ();
84                                 
85                                 return list.Capacity;
86                         }
87
88                         set {
89                                 if (list == null)
90                                         list = new ArrayList ();
91                                                               
92                                 list.Capacity = value;
93                         }
94                 }
95                 
96                 // Protected Instance Properties
97                 protected ArrayList InnerList {
98                         get {
99                                 if (list == null)
100                                         list = new ArrayList ();
101                                 return list;
102                         } 
103                 }
104                 
105                 protected IList List {get { return this; } }
106                 
107                 // Protected Instance Methods
108                 protected virtual void OnClear() { }
109                 protected virtual void OnClearComplete() { }
110                 
111                 protected virtual void OnInsert(int index, object value) { }
112                 protected virtual void OnInsertComplete(int index, object value) { }
113
114                 protected virtual void OnRemove(int index, object value) { }
115                 protected virtual void OnRemoveComplete(int index, object value) { }
116
117                 protected virtual void OnSet(int index, object oldValue, object newValue) { }
118                 protected virtual void OnSetComplete(int index, object oldValue, object newValue) { }
119
120                 protected virtual void OnValidate(object value) {
121                         if (null == value) {
122                                 throw new System.ArgumentNullException("CollectionBase.OnValidate: Invalid parameter value passed to method: null");
123                         }
124                 }
125                 
126                 // ICollection methods
127                 void ICollection.CopyTo(Array array, int index) {
128                         InnerList.CopyTo(array, index);
129                 }
130                 object ICollection.SyncRoot {
131                         get { return InnerList.SyncRoot; }
132                 }
133                 bool ICollection.IsSynchronized {
134                         get { return InnerList.IsSynchronized; }
135                 }
136
137                 // IList methods
138                 int IList.Add (object value) {
139                         int newPosition;
140                         OnValidate(value);
141                         newPosition = InnerList.Count;
142                         OnInsert(newPosition, value);
143                         InnerList.Add(value);
144                         try {
145                                 OnInsertComplete(newPosition, value);
146                         } catch {
147                                 InnerList.RemoveAt (newPosition);
148                                 throw;
149                         }
150                         
151                         return newPosition;
152                 }
153                 
154                 bool IList.Contains (object value) {
155                         return InnerList.Contains(value);
156                 }
157
158                 int IList.IndexOf (object value) {
159                         return InnerList.IndexOf(value);
160                 }
161
162                 void IList.Insert (int index, object value) {
163                         OnValidate(value);
164                         OnInsert(index, value);
165                         InnerList.Insert(index, value);
166                         try {
167                                 OnInsertComplete(index, value);
168                         } catch {
169                                 InnerList.RemoveAt (index);
170                                 throw;
171                         }
172                 }
173
174                 void IList.Remove (object value) {
175                         int removeIndex;
176                         OnValidate(value);
177                         removeIndex = InnerList.IndexOf(value);
178                         if (removeIndex == -1)
179                                 throw new ArgumentException ("The element cannot be found.", "value");
180                         OnRemove(removeIndex, value);
181                         InnerList.Remove(value);
182                         OnRemoveComplete(removeIndex, value);
183                 }
184
185                 // IList properties
186                 bool IList.IsFixedSize { 
187                         get { return InnerList.IsFixedSize; }
188                 }
189
190                 bool IList.IsReadOnly { 
191                         get { return InnerList.IsReadOnly; }
192                 }
193
194                 object IList.this[int index] { 
195                         get { return InnerList[index]; }
196                         set { 
197                                 if (index < 0 || index >= InnerList.Count)
198                                         throw new ArgumentOutOfRangeException ("index");
199
200                                 object oldValue;
201                                 // make sure we have been given a valid value
202                                 OnValidate(value);
203                                 // save a reference to the object that is in the list now
204                                 oldValue = InnerList[index];
205                                 
206                                 OnSet(index, oldValue, value);
207                                 InnerList[index] = value;
208                                 try {
209                                         OnSetComplete(index, oldValue, value);
210                                 } catch {
211                                         InnerList[index] = oldValue;
212                                         throw;
213                                 }
214                         }
215                 }
216         }
217 }