Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With Reactive Extensions (RX) how to solve compile error "cannot convert from 'method group' to 'System.IObserver"

When using IObservable, this line will not compile:

var x = receiver.Updates().Subscribe(OnNewMessage);

I get this error:

Error   3   Argument 1: cannot convert from 'method group' to 'System.IObserver<IMyClass>'      

And this error:

Error   2   The best overloaded method match for 'System.IObservable<IMyClass>.Subscribe(System.IObserver<IMyClass>)' has some invalid arguments    

The source code uses IObservable.

like image 676
Contango Avatar asked Jun 27 '14 11:06

Contango


2 Answers

The error

Argument 1: cannot convert from 'method group' to 'System.IObserver<IMyClass>' 

is quite clear provided you understand the terminology. It is raised because the .NET Framework Base Class Library System.IObservable<T> interface defines a single method with the signature:

IDisposable Subscribe(System.IObserver<T>)

and you are passing a method group. A method group is quite literally what it says, a group of methods. In particular, in this case it is the group of methods in scope with the name OnNewMessage. It is specified by passing a method name without parentheses. Using a method group is a shorthand that causes the compiler to use method overload resolution to find a method that can be converted to a typed delegate. Of course, no such method can exist for a type of System.IObserver<T> as it is not a typed delegate.

This error is crops up a lot when forgetting to include an assembly that contains a desired extension method and/or forgetting to include the using statement for the required namespace of that extension method.

In this case the intention was clearly to satisfy an extension method defined by the Reactive Extensions framework - Rx defines a number of extension methods on IObservable<T> that are a convenient shorthand for building an observer - that is a implementation of the System.IObserver<T> interface - and subscribing it to an observable in one go. The observer interface defines the following three methods:

void OnNext(T value);
void OnError<T>(Exception error);
void OnCompleted();

The various extension methods provided by Rx are defined in System.Reactive.Core and build an Observer implementation using supplied Actions in various combinations to fulfill the contract above. I've linked to the actual definition of these in the source of Rx. The simplest is the one that accepts an OnNext handler and provides a default implementation for the OnError and OnCompleted methods. It looks like this:

public static IDisposable Subscribe<T>(
    this IObservable<T> source, Action<T> onNext);

These extension methods are defined in the System namespace, so in addition to referencing the System.Reactive.Core assembly (in nuget packet Rx-Core, although most users will want at least the additional libraries provided by Rx-Main) you must also have a using System; declaration in your source file.

The second error:

The best overloaded method match for     
'System.IObservable<IMyClass>.Subscribe(System.IObserver<IMyClass>)'
has some invalid arguments.

is also in the same vein, confirming that best method the compiler could find (probably the only method of supplied method group in this case) was not convertible to the required type of the single IObserver<T> argument to the Subscribe method.

like image 50
James World Avatar answered Nov 14 '22 23:11

James World


This is a rather unhelpful error.

If you are using RX and IObservable, then the solution is to add the following assemblies to your project:

System.Reactive.Core.dll
System.Reactive.Interfaces.dll
System.Reactive.Linq.dll
System.Reactive.PlatformServices.dll

Alternatively, you can use NuGet to add Reactive Extensions to your project.

Once you add these assemblies, if you are using ReSharper, then it will helpfully offer to add the correct "using" directives.

like image 44
4 revs Avatar answered Nov 14 '22 23:11

4 revs