{"record":{"id":"1cb3f5c7a19084e9","repo":"dotnet/reactive","slug":"the-sender-parameter-of-the-event-is-not-assignable-to-0","errorCode":null,"errorMessage":"The sender parameter of the event is not assignable to '{0}'.","messagePattern":"The sender parameter of the event is not assignable to '(.+?)'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromEventPattern.cs","lineNumber":316,"sourceCode":"            {\n                isWinRT = true;\n\n                var pet = psr[0];\n                if (pet.ParameterType != addMethod.ReturnType)\n                    throw new InvalidOperationException(\"An event should either have add and remove methods that return void or an add method that returns a type compatible with the parameter type of the remove method.\");\n            }\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":298,"sourceCodeEnd":333,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromEventPattern.cs#L298-L333","documentation":"After checking parameter count, GetEventMethods verifies that the delegate's first parameter type is assignable to TSender (typically object). This InvalidOperationException fires when the sender slot of the delegate has a type that TSender cannot accept, so the FromEventPattern adapter cannot safely deliver the sender argument as TSender.","triggerScenarios":"Calling FromEventPattern<TSender, TEventArgs> with a delegate whose first Invoke parameter is a concrete type (e.g. MyControl) while TSender is a base type like object, or TSender set to a type unrelated to the delegate's actual sender parameter.","commonSituations":"Specifying an incorrect TSender generic argument (e.g. typeof(object) expected but the delegate narrows the sender); using custom delegates with strongly-typed senders; copy-pasting generic arguments from another event.","solutions":["Make TSender assignable-from the delegate's first parameter, typically use object for TSender","Match the delegate's sender parameter type exactly, e.g. FromEventPattern<MyControl, MyEventArgs> for a delegate taking (MyControl sender, MyEventArgs e)","Inspect the delegate: typeof(D).GetMethod(\"Invoke\").GetParameters()[0].ParameterType and ensure TSender.IsAssignableFrom(that type)"],"exampleFix":"// before\nAsyncObservable.FromEventPattern<object, MyEventArgs>(...) // delegate sender is MyControl, object is not assignable FROM MyControl? -> use actual types\n// after\nAsyncObservable.FromEventPattern<MyControl, MyEventArgs>(...)","handlingStrategy":"validation","validationCode":"var p = typeof(MyDelegate).GetMethod(\"Invoke\").GetParameters();\nif (!typeof(TSender).IsAssignableFrom(p[0].ParameterType))\n    throw new InvalidOperationException($\"TSender must accept {p[0].ParameterType}\");","typeGuard":"static bool SenderCompatible<TSender>(Type d)\n    => typeof(TSender).IsAssignableFrom(d.GetMethod(\"Invoke\")?.GetParameters()[0].ParameterType);","tryCatchPattern":"try\n{\n    var obs = AsyncObservable.FromEventPattern<TSender, TEventArgs>(add, remove);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"sender parameter\"))\n{\n    // retry with TSender = the delegate's actual sender parameter type\n}","preventionTips":["Use object as TSender unless you deliberately need a narrower type","Match TSender to the delegate's first Invoke parameter exactly","Avoid hand-copying generic arguments between different events"],"tags":["reflection","generics","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}