| File: System\Windows\Forms\NonNullCollection.cs | Web Access |
| Project: src\winforms\src\System.Windows.Forms.Primitives\src\System.Windows.Forms.Primitives.csproj (System.Windows.Forms.Primitives) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; namespace System.Windows.Forms; /// <summary> /// Collection that protects against inserting null objects. /// </summary> [DebuggerDisplay("{DebuggerDisplay,nq}")] internal abstract class NonNullCollection<T> : IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T> where T : class { private readonly List<T> _list = []; public NonNullCollection() { } public NonNullCollection(IEnumerable<T> items) => AddRange(items); public T this[int index] { get => _list[index]; set { _list[index] = value ?? ThrowArgumentNull(nameof(value)); ItemAdded(value); } } public int Count => _list.Count; public bool IsReadOnly => ((ICollection<T>)_list).IsReadOnly; public void Add(T item) { _list.Add(item ?? ThrowArgumentNull(nameof(item))); ItemAdded(item); } public void Clear() => _list.Clear(); public bool Contains(T item) => _list.Contains(item); public void CopyTo(T[] array, int arrayIndex) => _list.CopyTo(array, arrayIndex); public IEnumerator<T> GetEnumerator() => _list.GetEnumerator(); public int IndexOf(T item) => _list.IndexOf(item); public void Insert(int index, T item) { _list.Insert(index, item ?? ThrowArgumentNull(nameof(item))); ItemAdded(item); } public bool Remove(T item) => _list.Remove(item); public void RemoveAt(int index) => _list.RemoveAt(index); IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_list).GetEnumerator(); /// <summary> /// Adds the items in <paramref name="items"/> to the collection. /// </summary> public void AddRange(IEnumerable<T> items) { // We don't want to put in partial items, so we need to enumerate twice to throw appropriately. #pragma warning disable CA1851 // Possible multiple enumerations of 'IEnumerable' collection if (items is null || items.Contains(default)) { ThrowArgumentNull(nameof(items)); } _list.AddRange(items); foreach (T item in items) { ItemAdded(item); } #pragma warning restore CA1851 } int IList.Add(object? value) { int index = ((IList)_list).Add(value ?? ThrowArgumentNull(nameof(value))); ItemAdded((T)value); return index; } bool IList.Contains(object? value) => ((IList)_list).Contains(value); int IList.IndexOf(object? value) => ((IList)_list).IndexOf(value); void IList.Insert(int index, object? value) { ((IList)_list).Insert(index, value ?? ThrowArgumentNull(nameof(value))); ItemAdded((T)value); } void IList.Remove(object? value) => ((IList)_list).Remove(value); object? IList.this[int index] { get => ((IList)_list)[index]; set { ((IList)_list)[index] = value ?? ThrowArgumentNull(nameof(value)); ItemAdded((T)value); } } void ICollection.CopyTo(Array array, int index) => ((IList)_list).CopyTo(array, index); private string DebuggerDisplay => $"Count: {Count}"; bool IList.IsFixedSize => ((IList)_list).IsFixedSize; object ICollection.SyncRoot => ((ICollection)_list).SyncRoot; bool ICollection.IsSynchronized => ((ICollection)_list).IsSynchronized; /// <summary> /// Called for each item added to the collection. /// </summary> protected virtual void ItemAdded(T item) { } [DoesNotReturn] private static T ThrowArgumentNull(string name) => throw new ArgumentNullException(name); }