{"record":{"id":"e7f0a945bffd9644","repo":"dotnet/reactive","slug":"argumentnull-generic","errorCode":null,"errorMessage":"ArgumentNull_Generic","messagePattern":"ArgumentNull_Generic","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromEvent.Generated.cs","lineNumber":56,"sourceCode":"                throw new ArgumentNullException(nameof(conversion));\n            if (addHandler == null)\n                throw new ArgumentNullException(nameof(addHandler));\n            if (removeHandler == null)\n                throw new ArgumentNullException(nameof(removeHandler));\n\n            return FromEventCore<TDelegate, T1, T2>(conversion, addHandler, removeHandler, GetSchedulerForCurrentContext());\n        }\n\n        public static IAsyncObservable<(T1 arg1, T2 arg2)> FromEvent<TDelegate, T1, T2>(Func<Action<T1, T2>, TDelegate> conversion, Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IAsyncScheduler scheduler)\n        {\n            if (conversion == null)\n                throw new ArgumentNullException(nameof(conversion));\n            if (addHandler == null)\n                throw new ArgumentNullException(nameof(addHandler));\n            if (removeHandler == null)\n                throw new ArgumentNullException(nameof(removeHandler));\n            if (scheduler == null)\n                throw new ArgumentNullException(nameof(scheduler));\n\n            return FromEventCore<TDelegate, T1, T2>(conversion, addHandler, removeHandler, scheduler);\n        }\n\n        private static IAsyncObservable<(T1 arg1, T2 arg2)> FromEventCore<TDelegate, T1, T2>(Func<Action<T1, T2>, TDelegate> conversion, Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IAsyncScheduler scheduler)\n        {\n            return\n                SynchronizeEvents(\n                    Create<(T1 arg1, T2 arg2)>(observer =>\n                    {\n                        var handler = new Action<T1, T2>((arg1, arg2) =>\n                        {\n                            observer.OnNextAsync((arg1, arg2)); // REVIEW: Fire-and-forget can lead to out of order processing, and observers may reject these calls as \"busy\".\n                        });\n\n                        var converted = conversion(handler);\n\n                        addHandler(converted);","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromEvent.Generated.cs#L38-L74","documentation":"FromEvent converts .NET-style add/removeHandler event subscriptions into an async observable. This overload accepts a conversion delegate (Action<T1,T2> -> TDelegate), add/remove handlers, and a scheduler; it throws ArgumentNullException (rendered here as the generic ArgumentNull_Generic message) when any of `conversion`, `addHandler`, `removeHandler`, or `scheduler` is null.","triggerScenarios":"Calling the FromEvent<T1,T2> overload that takes (conversion, addHandler, removeHandler, scheduler) with any of those four arguments null - e.g. a scheduler obtained from a resolver that returned null, or an event handler registry with no add/remove hooks registered.","commonSituations":"Passing a scheduler from DI or a context provider that returned null; wiring events dynamically where the add/remove accessor delegates are null; forgetting the conversion lambda in the overload that requires it.","solutions":["Supply all four arguments: a conversion such as `h => ( EventHandler)h.Invoke` (matching TDelegate), non-null addHandler/removeHandler, and a scheduler like AsyncScheduler.Immediate (or the library's default).","Use the simpler overload FromEvent(addHandler, removeHandler) that internally supplies `h => h` conversion and GetSchedulerForCurrentContext() when you don't need custom conversion/scheduling.","Check the source of the scheduler argument; if it comes from configuration or a factory, assert non-null before calling."],"exampleFix":"// before\nAsyncObservable.FromEvent<Action<int,string>, int, string>(null, addHandler, removeHandler, null);\n// after\nvar conv = new Func<Action<int,string>, Action<int,string>>(h => h); // or real delegate conversion\nAsyncObservable.FromEvent<Action<int,string>, int, string>(conv, addHandler, removeHandler, AsyncScheduler.Immediate);","handlingStrategy":"validation","validationCode":"if (conversion is null || addHandler is null || removeHandler is null || scheduler is null)\n    throw new ArgumentNullException(conversion is null ? nameof(conversion)\n        : addHandler is null ? nameof(addHandler)\n        : removeHandler is null ? nameof(removeHandler) : nameof(scheduler));","typeGuard":"bool CanWire<TDel>(Func<Action<TDel>,TDel> conversion, Action<TDel> add, Action<TDel> remove, IAsyncScheduler sched)\n    => conversion is not null && add is not null && remove is not null && sched is not null;","tryCatchPattern":"try\n{\n    var obs = AsyncObservable.FromEvent<TDelegate,int,string>(conversion, addHandler, removeHandler, scheduler);\n}\ncatch (ArgumentNullException ex)\n{\n    // ex.ParamName tells which of conversion/addHandler/removeHandler/scheduler was null\n}","preventionTips":["Use the two-argument FromEvent overload unless you specifically need custom conversion or scheduler.","Resolve the scheduler from a guaranteed default (AsyncScheduler.Immediate / Default) rather than nullable DI lookups.","Keep event add/remove accessors as +=/-= lambdas on a fully constructed target."],"tags":["csharp","argumentnull","events","scheduler"],"backgroundTag":"null-argument","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"}