{"record":{"id":"a0ce37c27be81339","repo":"dotnet/reactive","slug":"the-return-type-of-an-event-delegate-should-be-void","errorCode":null,"errorMessage":"The return type of an event delegate should be void.","messagePattern":"The return type of an event delegate should be void\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromEventPattern.cs","lineNumber":322,"sourceCode":"            }\n\n            var delegateType = psa[0].ParameterType;\n\n            var invokeMethod = delegateType.GetMethod(\"Invoke\");\n\n            var parameters = invokeMethod.GetParameters();\n\n            if (parameters.Length != 2)\n                throw new InvalidOperationException(\"The delegate type for an event conforming to the traditional event pattern should take two parameters.\");\n\n            if (!typeof(TSender).IsAssignableFrom(parameters[0].ParameterType))\n                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, \"The sender parameter of the event is not assignable to '{0}'.\", typeof(TSender).FullName));\n\n            if (!typeof(TEventArgs).IsAssignableFrom(parameters[1].ParameterType))\n                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, \"The event arguments parameter of the event is not assignable to '{0}'.\", typeof(TEventArgs).FullName));\n\n            if (invokeMethod.ReturnType != typeof(void))\n                throw new InvalidOperationException(\"The return type of an event delegate should be void.\");\n\n            return (addMethod, removeMethod, delegateType, isWinRT);\n        }\n\n        public static EventInfo GetEventEx(this Type type, string name, bool isStatic)\n        {\n            return type.GetEvent(name, isStatic ? BindingFlags.Public | BindingFlags.Static : BindingFlags.Public | BindingFlags.Instance);\n        }\n    }\n}\n","sourceCodeStart":304,"sourceCodeEnd":333,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromEventPattern.cs#L304-L333","documentation":"Event delegates must return void; GetEventMethods rejects any delegate whose Invoke method returns a non-void type with this InvalidOperationException. Reactive event bridging only supports handlers that produce values through their arguments, not through a return value.","triggerScenarios":"Passing a delegate type with a non-void return (e.g. Func<object, TEventArgs, bool> or a custom delegate returning a value) to the reflection-based FromEventPattern overloads.","commonSituations":"Reusing functional delegates (predicate/validator style) as event handlers; custom message-bus delegate types that return a result; accidental use of Func instead of Action/EventHandler shapes.","solutions":["Use a delegate type returning void, e.g. EventHandler<TEventArgs> or a custom void-returning delegate matching the event","If the underlying API genuinely needs a return value, wrap the event manually with Create/Subscribe and an add/remove pair that adapts the signature","Verify with typeof(D).GetMethod(\"Invoke\").ReturnType == typeof(void) before calling"],"exampleFix":"// before\ndelegate bool MyHandler(object sender, MyEventArgs e);\n// after\ndelegate void MyHandler(object sender, MyEventArgs e);","handlingStrategy":"validation","validationCode":"if (typeof(MyDelegate).GetMethod(\"Invoke\").ReturnType != typeof(void))\n    throw new InvalidOperationException(\"Event delegates must return void\");","typeGuard":"static bool IsVoidDelegate(Type d)\n    => d.GetMethod(\"Invoke\")?.ReturnType == typeof(void);","tryCatchPattern":"try\n{\n    var obs = AsyncObservable.FromEventPattern<TSender, TEventArgs>(add, remove);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"return type\"))\n{\n    // define/use a void-returning delegate instead\n}","preventionTips":["Never use Func-style (value-returning) delegates as event handlers","Declare custom event delegates with void return","Check ReturnType == typeof(void) when accepting delegate types dynamically"],"tags":["reflection","events","argument-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}