2005-09-29 Miguel de Icaza <miguel@novell.com>
[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 #if NET_2_0
39         [ComVisible(true)]
40 #endif
41         [Serializable]
42         public abstract class CollectionBase : IList, ICollection, IEnumerable {
43
44                 // private instance properties
45                 private ArrayList list;
46                 
47                 // public instance properties
48                 public int Count { get { return InnerList.Count; } }
49                 
50                 // Public Instance Methods
51                 public IEnumerator GetEnumerator() { return InnerList.GetEnumerator(); }
52                 public void Clear() { 
53                         OnClear();
54                         InnerList.Clear(); 
55                         OnClearComplete();
56                 }
57                 public void RemoveAt (int index) {
58                         object objectToRemove;
59                         objectToRemove = InnerList[index];
60                         OnValidate(objectToRemove);
61                         OnRemove(index, objectToRemove);
62                         InnerList.RemoveAt(index);
63                         OnRemoveComplete(index, objectToRemove);
64                 }
65                 
66                 // Protected Instance Constructors
67                 protected CollectionBase()
68                 { 
69                 }
70
71 #if NET_2_0
72                 protected CollectionBase (int capacity)
73                 {
74                         list = new ArrayList (capacity);
75                 }
76
77                 public int Capacity {
78                         get {
79                                 if (list == null)
80                                         list = new ArrayList ();
81                                 
82                                 return list.Capacity;
83                         }
84
85                         set {
86                                 if (list == null)
87                                         list = new ArrayList ();
88                                                               
89                                 list.Capacity = value;
90                         }
91                 }
92                         
93 #endif
94                 
95                 // Protected Instance Properties
96                 protected ArrayList InnerList {
97                         get {
98                                 if (list == null)
99                                         list = new ArrayList ();
100                                 return list;
101                         } 
102                 }
103                 
104                 protected IList List {get { return this; } }
105                 
106                 // Protected Instance Methods
107                 protected virtual void OnClear() { }
108                 protected virtual void OnClearComplete() { }
109                 
110                 protected virtual void OnInsert(int index, object value) { }
111                 protected virtual void OnInsertComplete(int index, object value) { }
112
113                 protected virtual void OnRemove(int index, object value) { }
114                 protected virtual void OnRemoveComplete(int index, object value) { }
115
116                 protected virtual void OnSet(int index, object oldValue, object newValue) { }
117                 protected virtual void OnSetComplete(int index, object oldValue, object newValue) { }
118
119                 protected virtual void OnValidate(object value) {
120                         if (null == value) {
121                                 throw new System.ArgumentNullException("CollectionBase.OnValidate: Invalid parameter value passed to method: null");
122                         }
123                 }
124                 
125                 // ICollection methods
126                 void ICollection.CopyTo(Array array, int index) {
127                         InnerList.CopyTo(array, index);
128                 }
129                 object ICollection.SyncRoot {
130                         get { return InnerList.SyncRoot; }
131                 }
132                 bool ICollection.IsSynchronized {
133                         get { return InnerList.IsSynchronized; }
134                 }
135
136                 // IList methods
137                 int IList.Add (object value) {
138                         int newPosition;
139                         OnValidate(value);
140                         newPosition = InnerList.Count;
141                         OnInsert(newPosition, value);
142                         InnerList.Add(value);
143                         try {
144                                 OnInsertComplete(newPosition, value);
145                         } catch {
146                                 InnerList.RemoveAt (newPosition);
147                                 throw;
148                         }
149                         
150                         return newPosition;
151                 }
152                 
153                 bool IList.Contains (object value) {
154                         return InnerList.Contains(value);
155                 }
156
157                 int IList.IndexOf (object value) {
158                         return InnerList.IndexOf(value);
159                 }
160
161                 void IList.Insert (int index, object value) {
162                         OnValidate(value);
163                         OnInsert(index, value);
164                         InnerList.Insert(index, value);
165                         try {
166                                 OnInsertComplete(index, value);
167                         } catch {
168                                 InnerList.RemoveAt (index);
169                                 throw;
170                         }
171                 }
172
173                 void IList.Remove (object value) {
174                         int removeIndex;
175                         OnValidate(value);
176                         removeIndex = InnerList.IndexOf(value);
177                         if (removeIndex == -1)
178                                 throw new ArgumentException ("The element cannot be found.", "value");
179                         OnRemove(removeIndex, value);
180                         InnerList.Remove(value);
181                         OnRemoveComplete(removeIndex, value);
182                 }
183
184                 // IList properties
185                 bool IList.IsFixedSize { 
186                         get { return InnerList.IsFixedSize; }
187                 }
188
189                 bool IList.IsReadOnly { 
190                         get { return InnerList.IsReadOnly; }
191                 }
192
193                 object IList.this[int index] { 
194                         get { return InnerList[index]; }
195                         set { 
196                                 if (index < 0 || index >= InnerList.Count)
197                                         throw new ArgumentOutOfRangeException ("index");
198
199                                 object oldValue;
200                                 // make sure we have been given a valid value
201                                 OnValidate(value);
202                                 // save a reference to the object that is in the list now
203                                 oldValue = InnerList[index];
204                                 
205                                 OnSet(index, oldValue, value);
206                                 InnerList[index] = value;
207                                 try {
208                                         OnSetComplete(index, oldValue, value);
209                                 } catch {
210                                         InnerList[index] = oldValue;
211                                         throw;
212                                 }
213                         }
214                 }
215         }
216 }