{"record":{"id":"143344645f72a3ad","repo":"dotnet/reactive","slug":"conversion-windowsobservable-events","errorCode":null,"errorMessage":"conversion","messagePattern":"conversion","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Platforms/WinRT/Linq/WindowsObservable.Events.cs","lineNumber":70,"sourceCode":"        }\n\n        /// <summary>\n        /// Converts a typed event, conforming to the standard event pattern, to an observable sequence.\n        /// </summary>\n        /// <typeparam name=\"TDelegate\">The delegate type of the event to be converted.</typeparam>\n        /// <typeparam name=\"TSender\">The type of the sender that raises the event.</typeparam>\n        /// <typeparam name=\"TResult\">The type of the event data generated by the event.</typeparam>\n        /// <param name=\"conversion\">A function used to convert the given event handler to a delegate compatible with the underlying typed event. The resulting delegate is used in calls to the addHandler and removeHandler action parameters.</param>\n        /// <param name=\"addHandler\">Action that attaches the given event handler to the underlying .NET event.</param>\n        /// <param name=\"removeHandler\">Action that detaches the given event handler from the underlying .NET event.</param>\n        /// <returns>The observable sequence that contains data representations of invocations of the underlying typed event.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"conversion\"/> or <paramref name=\"addHandler\"/> or <paramref name=\"removeHandler\"/> is null.</exception>\n        /// <seealso cref=\"ToEventPattern\"/>\n        public static IObservable<EventPattern<TSender, TResult>> FromEventPattern<TDelegate, TSender, TResult>(Func<TypedEventHandler<TSender, TResult>, TDelegate> conversion, Action<TDelegate> addHandler, Action<TDelegate> removeHandler)\n        {\n            if (conversion == null)\n            {\n                throw new ArgumentNullException(nameof(conversion));\n            }\n\n            if (addHandler == null)\n            {\n                throw new ArgumentNullException(nameof(addHandler));\n            }\n\n            if (removeHandler == null)\n            {\n                throw new ArgumentNullException(nameof(removeHandler));\n            }\n\n            return Observable.Create<EventPattern<TSender, TResult>>(observer =>\n            {\n                var h = conversion(new TypedEventHandler<TSender, TResult>((sender, args) =>\n                {\n                    observer.OnNext(new EventPattern<TSender, TResult>(sender, args));\n                }));","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Platforms/WinRT/Linq/WindowsObservable.Events.cs#L52-L88","documentation":"This FromEventPattern overload converts a TypedEventHandler to a custom delegate type and throws ArgumentNullException when the conversion function is null. The conversion is what adapts the WinRT handler to the target delegate, so it is mandatory.","triggerScenarios":"Calling Observable.FromEventPattern<TDelegate,TSender,TResult>(conversion, addHandler, removeHandler) with a null conversion Func, e.g. when the conversion was computed dynamically (Delegate.CreateDelegate) and returned null.","commonSituations":"Reflection-based delegate construction failing silently; passing null when the target delegate type already matches and the developer assumed conversion was optional.","solutions":["Supply an explicit conversion such as h => (MyEventHandler)h if types align, or write a wrapper lambda","If Delegate.CreateDelegate is used, check its result for null before calling FromEventPattern","Prefer the non-conversion overload when TDelegate already is TypedEventHandler<TSender,TResult>","Use a lambda wrapper instead of reflection conversion to avoid null results"],"exampleFix":"// before\nFunc<TypedEventHandler<Button, RoutedEventArgs>, RoutedEventHandler> conv = null;\nObservable.FromEventPattern<RoutedEventHandler, Button, RoutedEventArgs>(conv, a => b.Click += a, r => b.Click -= r);\n// after\nObservable.FromEventPattern<RoutedEventHandler, Button, RoutedEventArgs>(\n    h => new RoutedEventHandler((s, e) => h(s, e)),\n    a => button.Click += a,\n    r => button.Click -= r);","handlingStrategy":"validation","validationCode":"if (conversion == null) throw new ArgumentNullException(nameof(conversion));\nvar converted = conversion(handler); // ensure Delegate.CreateDelegate result is checked","typeGuard":"static bool HasConversion<TDel, T>(Func<T, TDel> conv) => conv != null;","tryCatchPattern":"try { var obs = Observable.FromEventPattern<TDelegate, TSender, TResult>(conversion, add, remove); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"conversion\") { /* use a wrapper lambda instead */ }","preventionTips":["Use explicit lambda wrappers for delegate conversion instead of reflection","Check Delegate.CreateDelegate results for null before use","Prefer the overload without conversion when delegate types already match","Document required delegates in event-wiring helpers"],"tags":["rx","null-argument","events","winrt","delegates"],"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"}