Search code examples
c#genericscastingsystem.reactiveunirx

Invalid cast of IObservable, runtime exception


I'm creating a helper to filter specific types of objects in a stream/observable. This is the gist:

public interface IGameAction { }

// Example action
public struct OpenDoorAction : IGameAction { }

// In Store.cs
public Subject<IGameAction> Actions;

public IObservable<T> When<T>() where T : IGameAction
{
    // Exception here
    return (IObservable<T>)this.Actions.Where(action => action is T);
}

When used like this:

this.When<OpenDoorAction>()
    .Subscribe(a => Debug.Log(a));

The following exception is thrown for the line marked above:

InvalidCastException: Specified cast is not valid.

I have tried using classes for either and both of IGameAction and the implementors (eg. OpenDoorAction). I don't understand why I need the cast to IObservable<T>, but without it the compiler says there is no implicit cast from IObservable<IGameAction> to IObservable<T>. Subject implements IObservable.

FWIW this is in Unity3D using UniRx


Solution

  • This is because there's no direct cast between IObservable<IGameAction> and the IObservable<T> even though you've specified the constraint.

    You should instead re-cast the individual items in the stream:

    return this.Actions.Where(action => action is T).Cast<T>();

    And your return value will then be an IObservable of the correct type.


    As mjwills points out in the comments, a helper function of IObservable<T>.OfType<T2> exists, which basically just does the where and cast for you.