{"record":{"id":"39c4a966eceb91a7","repo":"dotnet/reactive","slug":"the-remove-method-of-an-event-should-take-one-parameter","errorCode":null,"errorMessage":"The remove method of an event should take one parameter.","messagePattern":"The remove method of an event should take one parameter\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromEventPattern.cs","lineNumber":293,"sourceCode":"                if (e == null)\n                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, \"Could not find instance event '{0}' on type '{1}'.\", eventName, targetType.FullName));\n            }\n\n            var addMethod = e.GetAddMethod();\n            var removeMethod = e.GetRemoveMethod();\n\n            if (addMethod == null)\n                throw new InvalidOperationException(\"Missing add method on event.\");\n            if (removeMethod == null)\n                throw new InvalidOperationException(\"Missing remove method on event.\");\n\n            var psa = addMethod.GetParameters();\n            if (psa.Length != 1)\n                throw new InvalidOperationException(\"The add method of an event should take one parameter.\");\n\n            var psr = removeMethod.GetParameters();\n            if (psr.Length != 1)\n                throw new InvalidOperationException(\"The remove method of an event should take one parameter.\");\n\n            var isWinRT = false;\n\n            if (addMethod.ReturnType != typeof(void))\n            {\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","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromEventPattern.cs#L275-L311","documentation":"Symmetric to the add accessor check: the remove accessor must take exactly one delegate parameter. GetEventMethods throws InvalidOperationException when removeMethod.GetParameters() has a length other than 1.","triggerScenarios":"Events whose remove accessor signature deviates from the CLR event pattern (custom IL, weaved code, or platform projections with extra parameters).","commonSituations":"Custom event store implementations with a removal token parameter, post-processing tools altering signatures, mis-declared events in COM/WinRT interop layers.","solutions":["Fix the event declaration to the standard pattern: remove takes a single delegate parameter","If an extra token is genuinely needed, use the FromEvent overload with explicit add/remove delegates instead of name-based lookup","Inspect removeMethod.GetParameters() to confirm the offending signature"],"exampleFix":"// before\npublic event EventHandler Tick {\n  add { _tick += value; }\n  remove { _tick -= value; _token = null; } // ok; but IL with (delegate, token) breaks\n}\n// after\npublic event EventHandler Tick; // standard accessors, one parameter each","handlingStrategy":"validation","validationCode":"var ev = type.GetEvent(eventName);\nvar remove = ev?.GetRemoveMethod();\nif (remove is null || remove.GetParameters().Length != 1) throw new NotSupportedException($\"Event '{eventName}' remove accessor must take exactly one delegate parameter.\");","typeGuard":"static bool HasValidRemoveSignature(Type t, string name) => t.GetEvent(name)?.GetRemoveMethod()?.GetParameters().Length == 1;","tryCatchPattern":null,"preventionTips":["Keep remove accessors to the standard single-delegate signature","Verify events after any IL post-processing step","Avoid custom remove tokens; use FromEvent with explicit delegates instead"],"tags":["csharp","reflection","event-signature","invalid-operation"],"backgroundTag":"unsupported-operation","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"}