| File: WeakList.cs | Web Access |
| Project: src\src\Core\src\Core.csproj (Microsoft.Maui) |
#nullable enable using System; using System.Collections; using System.Collections.Generic; namespace Microsoft.Maui; /// <summary> /// A List type for holding WeakReference's /// It clears the underlying List based on a threshold of operations: Add() or GetEnumerator() /// </summary> class WeakList<T> : IEnumerable<T> where T : class { readonly List<WeakReference<T>> _list = new(); int _operations; public int Count => _list.Count; public int CleanupThreshold { get; set; } = 32; public void Add(T item) { CleanupIfNeeded(); _list.Add(new WeakReference<T>(item)); } public void Remove(T item) { WeakReference<T> w; // A reverse for-loop, means we can call RemoveAt(i) inside the loop for (int i = _list.Count - 1; i >= 0; i--) { w = _list[i]; if (w.TryGetTarget(out T? target)) { if (target == item) { _list.RemoveAt(i); break; } } else { // Remove if we found one that is not alive _list.RemoveAt(i); } } } public void Clear() { _list.Clear(); _operations = 0; } public IEnumerator<T> GetEnumerator() { CleanupIfNeeded(); foreach (var w in _list) if (w.TryGetTarget(out T? item)) yield return item; } void CleanupIfNeeded() { if (++_operations > CleanupThreshold) { _operations = 0; _list.RemoveAll(w => !w.TryGetTarget(out _)); } } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); }