Fix IDE0025 (use expression body for properties)
[mono-project.git] / netcore / System.Private.CoreLib / shared / System / Collections / ObjectModel / Collection.cs
blob1541cfeb65979b0c4a025b10134547985f89095d
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System.Collections.Generic;
6 using System.Diagnostics;
8 namespace System.Collections.ObjectModel
10 [Serializable]
11 [DebuggerTypeProxy(typeof(ICollectionDebugView<>))]
12 [DebuggerDisplay("Count = {Count}")]
13 [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
14 public class Collection<T> : IList<T>, IList, IReadOnlyList<T>
16 private readonly IList<T> items; // Do not rename (binary serialization)
18 public Collection()
20 items = new List<T>();
23 public Collection(IList<T> list)
25 if (list == null)
27 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.list);
29 items = list;
32 public int Count => items.Count;
34 protected IList<T> Items => items;
36 public T this[int index]
38 get { return items[index]; }
39 set
41 if (items.IsReadOnly)
43 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
46 if ((uint)index >= (uint)items.Count)
48 ThrowHelper.ThrowArgumentOutOfRange_IndexException();
51 SetItem(index, value);
55 public void Add(T item)
57 if (items.IsReadOnly)
59 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
62 int index = items.Count;
63 InsertItem(index, item);
66 public void Clear()
68 if (items.IsReadOnly)
70 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
73 ClearItems();
76 public void CopyTo(T[] array, int index)
78 items.CopyTo(array, index);
81 public bool Contains(T item)
83 return items.Contains(item);
86 public IEnumerator<T> GetEnumerator()
88 return items.GetEnumerator();
91 public int IndexOf(T item)
93 return items.IndexOf(item);
96 public void Insert(int index, T item)
98 if (items.IsReadOnly)
100 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
103 if ((uint)index > (uint)items.Count)
105 ThrowHelper.ThrowArgumentOutOfRange_IndexException();
108 InsertItem(index, item);
111 public bool Remove(T item)
113 if (items.IsReadOnly)
115 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
118 int index = items.IndexOf(item);
119 if (index < 0) return false;
120 RemoveItem(index);
121 return true;
124 public void RemoveAt(int index)
126 if (items.IsReadOnly)
128 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
131 if ((uint)index >= (uint)items.Count)
133 ThrowHelper.ThrowArgumentOutOfRange_IndexException();
136 RemoveItem(index);
139 protected virtual void ClearItems()
141 items.Clear();
144 protected virtual void InsertItem(int index, T item)
146 items.Insert(index, item);
149 protected virtual void RemoveItem(int index)
151 items.RemoveAt(index);
154 protected virtual void SetItem(int index, T item)
156 items[index] = item;
159 bool ICollection<T>.IsReadOnly => items.IsReadOnly;
161 IEnumerator IEnumerable.GetEnumerator()
163 return ((IEnumerable)items).GetEnumerator();
166 bool ICollection.IsSynchronized => false;
168 object ICollection.SyncRoot => items is ICollection coll ? coll.SyncRoot : this;
170 void ICollection.CopyTo(Array array, int index)
172 if (array == null)
174 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
177 if (array.Rank != 1)
179 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
182 if (array.GetLowerBound(0) != 0)
184 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
187 if (index < 0)
189 ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
192 if (array.Length - index < Count)
194 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
197 if (array is T[] tArray)
199 items.CopyTo(tArray, index);
201 else
204 // Catch the obvious case assignment will fail.
205 // We can't find all possible problems by doing the check though.
206 // For example, if the element type of the Array is derived from T,
207 // we can't figure out if we can successfully copy the element beforehand.
209 Type targetType = array.GetType().GetElementType()!;
210 Type sourceType = typeof(T);
211 if (!(targetType.IsAssignableFrom(sourceType) || sourceType.IsAssignableFrom(targetType)))
213 ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType();
217 // We can't cast array of value type to object[], so we don't support
218 // widening of primitive types here.
220 object?[]? objects = array as object[];
221 if (objects == null)
223 ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType();
226 int count = items.Count;
229 for (int i = 0; i < count; i++)
231 objects[index++] = items[i];
234 catch (ArrayTypeMismatchException)
236 ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType();
241 object? IList.this[int index]
243 get { return items[index]; }
246 ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value);
248 T item = default(T)!;
252 item = (T)value!;
254 catch (InvalidCastException)
256 ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T));
259 this[index] = item;
263 bool IList.IsReadOnly => items.IsReadOnly;
265 bool IList.IsFixedSize
269 // There is no IList<T>.IsFixedSize, so we must assume that only
270 // readonly collections are fixed size, if our internal item
271 // collection does not implement IList. Note that Array implements
272 // IList, and therefore T[] and U[] will be fixed-size.
273 if (items is IList list)
275 return list.IsFixedSize;
277 return items.IsReadOnly;
281 int IList.Add(object? value)
283 if (items.IsReadOnly)
285 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
287 ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value);
289 T item = default(T)!;
293 item = (T)value!;
295 catch (InvalidCastException)
297 ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T));
300 Add(item);
302 return this.Count - 1;
305 bool IList.Contains(object? value)
307 if (IsCompatibleObject(value))
309 return Contains((T)value!);
311 return false;
314 int IList.IndexOf(object? value)
316 if (IsCompatibleObject(value))
318 return IndexOf((T)value!);
320 return -1;
323 void IList.Insert(int index, object? value)
325 if (items.IsReadOnly)
327 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
329 ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value);
331 T item = default(T)!;
335 item = (T)value!;
337 catch (InvalidCastException)
339 ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T));
342 Insert(index, item);
345 void IList.Remove(object? value)
347 if (items.IsReadOnly)
349 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
352 if (IsCompatibleObject(value))
354 Remove((T)value!);
358 private static bool IsCompatibleObject(object? value)
360 // Non-null values are fine. Only accept nulls if T is a class or Nullable<U>.
361 // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
362 return ((value is T) || (value == null && default(T)! == null));