DotNext by Roman Sakno

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

 ValueAction<T>

Represents a pointer to the method with single parameter and Void return type.
using System; using System.ComponentModel; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace DotNext { [StructLayout(LayoutKind.Auto)] public readonly struct ValueAction<T> : ICallable<Action<T>>, ICallable, IEquatable<ValueAction<T>>, IConsumer<T> { private readonly IntPtr methodPtr; private readonly Action<T> action; public bool IsEmpty { get { if (action == null) return methodPtr == (IntPtr)0; return false; } } public object Target => action?.Target; public ValueAction(MethodInfo method) { this = new ValueAction<T>(DelegateHelpers.CreateDelegate<Action<T>>(method, (object)null), false); } public ValueAction(Action<T> action, bool wrap = false) { if (action == null) throw new ArgumentNullException("action"); if (wrap || DelegateHelpers.IsRegularDelegate(action)) { this.action = action; methodPtr = default(IntPtr); } else { this.action = null; methodPtr = action.Method.MethodHandle.GetFunctionPointer(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] [EditorBrowsable(EditorBrowsableState.Never)] [CLSCompliant(false)] public ValueAction(IntPtr methodPtr) { action = null; this.methodPtr = methodPtr; } public Action<T> ToDelegate() { if (methodPtr != (IntPtr)0) return new Action<T>(null, methodPtr); return action; } public void Invoke(T arg) { if (methodPtr != (IntPtr)0) ; else action(arg); } object ICallable.DynamicInvoke(params object[] args) { Invoke((T)args[0]); return null; } public static explicit operator Action<T>([In] [System.Runtime.CompilerServices.IsReadOnly] ref ValueAction<T> pointer) { return pointer.ToDelegate(); } public override int GetHashCode() { return action?.GetHashCode() ?? methodPtr.GetHashCode(); } public bool Equals(ValueAction<T> other) { if (methodPtr == other.methodPtr) return object.Equals(action, other.action); return false; } public override bool Equals(object other) { if (other is ValueAction<T>) { ValueAction<T> other2 = (ValueAction<T>)other; return Equals(other2); } return false; } public override string ToString() { return action?.ToString() ?? methodPtr.ToString("X"); } public static bool operator ==([In] [System.Runtime.CompilerServices.IsReadOnly] ref ValueAction<T> first, [In] [System.Runtime.CompilerServices.IsReadOnly] ref ValueAction<T> second) { if (first.methodPtr == second.methodPtr) return object.Equals(first.action, second.action); return false; } public static bool operator !=([In] [System.Runtime.CompilerServices.IsReadOnly] ref ValueAction<T> first, [In] [System.Runtime.CompilerServices.IsReadOnly] ref ValueAction<T> second) { if (!(first.methodPtr != second.methodPtr)) return !object.Equals(first.action, second.action); return true; } } }