DotNext by .NET Foundation and Contributors

<PackageReference Include="DotNext" Version="4.4.1" />

 InvocationList<TDelegate>

public struct InvocationList<TDelegate> : IReadOnlyCollection<TDelegate>, IEnumerable<TDelegate>, IEnumerable where TDelegate : MulticastDelegate
Represents immutable list of delegates.
using DotNext.Collections.Generic; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace DotNext.Collections.Specialized { [StructLayout(LayoutKind.Auto)] [System.Runtime.CompilerServices.NullableContext(2)] [System.Runtime.CompilerServices.Nullable(0)] public readonly struct InvocationList<[System.Runtime.CompilerServices.Nullable(0)] TDelegate> : IReadOnlyCollection<TDelegate>, IEnumerable<TDelegate>, IEnumerable where TDelegate : MulticastDelegate { [StructLayout(LayoutKind.Auto)] [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public struct Enumerator { private object list; private int index; public TDelegate Current { [IsReadOnly] get; private set; } internal Enumerator(object list) { this.list = list; index = -1; Current = null; } public bool MoveNext() { if (list != null) { if (list is TDelegate) { Current = Unsafe.As<TDelegate>(list); list = null; } else { TDelegate[] array = Unsafe.As<TDelegate[]>(list); index++; if ((uint)index >= (uint)array.Length) goto IL_0068; Current = array[index]; } return true; } goto IL_0068; IL_0068: return false; } } private readonly object list; [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public static InvocationList<TDelegate> Empty { [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] get { return default(InvocationList<TDelegate>); } } public bool IsEmpty => list == null; public int Count { get { object obj = list; if (obj == null) return 0; if (obj is TDelegate) return 1; return Unsafe.As<TDelegate[]>(list).Length; } } [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] [DebuggerBrowsable(DebuggerBrowsableState.Never)] internal ReadOnlySpan<TDelegate> Span { get { object obj = list; if (obj == null) return ReadOnlySpan<TDelegate>.Empty; if (obj is TDelegate) return MemoryMarshal.CreateReadOnlySpan<TDelegate>(ref Unsafe.As<object, TDelegate>(ref Unsafe.AsRef<object>(ref list)), 1); return Unsafe.As<TDelegate[]>(list); } } [System.Runtime.CompilerServices.NullableContext(1)] public InvocationList(TDelegate d) { list = d; } private InvocationList(TDelegate[] array, TDelegate d) { Array.Resize<TDelegate>(ref array, array.Length + 1); array[array.Length - 1] = d; list = array; } private InvocationList(TDelegate d1, TDelegate d2) { list = new TDelegate[2] { d1, d2 }; } private InvocationList(TDelegate[] array) { list = array; } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public InvocationList<TDelegate> Add(TDelegate d) { if (d != null) { object obj = list; return (obj == null) ? new InvocationList<TDelegate>(d) : ((!(obj is TDelegate)) ? new InvocationList<TDelegate>(Unsafe.As<TDelegate[]>(list), d) : new InvocationList<TDelegate>(Unsafe.As<TDelegate>(list), d)); } return this; } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public InvocationList<TDelegate> Remove(TDelegate d) { if (d != null && list != null) { InvocationList<TDelegate> result; if (object.Equals(list, d)) result = default(InvocationList<TDelegate>); else { TDelegate[] array = Unsafe.As<TDelegate[]>(list); long num = Array.IndexOf<TDelegate>(array, d); if (num >= 0) array = OneDimensionalArray.RemoveAt<TDelegate>(array, num); result = new InvocationList<TDelegate>(array); } return result; } return this; } public TDelegate Combine() { object obj = list; if (obj == null) return null; if (obj is TDelegate) return Unsafe.As<TDelegate>(list); Delegate[] delegates = Unsafe.As<TDelegate[]>(list); return Delegate.Combine(delegates) as TDelegate; } public static InvocationList<TDelegate>operator +([System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] InvocationList<TDelegate> list, TDelegate d) { return list.Add(d); } public static InvocationList<TDelegate>operator -([System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] InvocationList<TDelegate> list, TDelegate d) { return list.Remove(d); } [System.Runtime.CompilerServices.NullableContext(0)] public Enumerator GetEnumerator() { return new Enumerator(list); } private IEnumerator<TDelegate> GetEnumeratorCore() { object obj = list; if (obj == null) return Sequence.GetEmptyEnumerator<TDelegate>(); TDelegate val = obj as TDelegate; if (val != null) return new SingletonList<TDelegate>.Enumerator(val); return Unsafe.As<IEnumerable<TDelegate>>(list).GetEnumerator(); } IEnumerator<TDelegate> IEnumerable<TDelegate>.GetEnumerator() { return GetEnumeratorCore(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumeratorCore(); } } }