C# 有没有办法避免这种c类型的推理失败?

C# 有没有办法避免这种c类型的推理失败?,c#,system.reactive,type-inference,C#,System.reactive,Type Inference,我有以下IObserver的C扩展方法。它使我能够通过使用中间主题将LINQ表达式放在它的前面 /// <summary> /// Given an IObserver we may wish to build a new IObserver that has LINQ /// combinators at it's head. /// /// observer = observer.Wrap(observable=>observable.Where(k=>k&g

我有以下IObserver的C扩展方法。它使我能够通过使用中间主题将LINQ表达式放在它的前面

/// <summary>
/// Given an IObserver we may wish to build a new IObserver that has LINQ
/// combinators at it's head.
///
///     observer = observer.Wrap(observable=>observable.Where(k=>k>0));
///
/// </summary>
public static IObserver<U>
 Wrap<T,U>
 ( this IObserver<T> This
 , Func<IObservable<U>, IObservable<T>> fn 
 )
{
    var s = new Subject<U>();
    fn(s).Subscribe(This);
    return s;
}
但是当我使用这个方法的时候

    [Fact]
    public void WrapShouldWrapObservers()
    {
        var b = new List<int>() { 0, 1, 2,3,4,5 };
        var s = new Subject<int>();
        var c = new List<int>();

        var obs = s.Wrap(observable => observable.Where(k => k > 3));

        s.Subscribe(v => c.Add(v));

        b.ToObservable().Subscribe(obs);
        c.Should().BeEquivalentTo(4, 5);

    }
我得到的错误是

Error   2   The type arguments for method

ReactiveUI.Ext.IObservableMixins.Wrap<T,U>
( System.IObserver<T>
, System.Func<System.IObservable<U>,System.IObservable<T>>
)

cannot be inferred from the usage. Try specifying the type arguments
explicitly. 
当我显式地输入args类型时,它就工作了

    var obs = s.Wrap<int,int>(observable => observable.Where(k => k > 3));
但是,从检查来看,如果我不使用类型args,就不会有歧义。这里有什么问题

------答复------

如果我更改测试用例以正确地使用这些类型,那么问题就显而易见了

    [Fact]
    public void WrapShouldWrapObservers()
    {
        var b = new List<int>() { 0, 1, 2,3,4,5 };
        var s = new Subject<string>();
        var c = new List<string>();

        var obs2 = s.Wrap<int,string>(observable => observable.Where(k => k > 3).Select(k=>k.ToString()));

        s.Subscribe(v => c.Add(v));

        b.ToObservable().Subscribe(obs2);
        c.Should().BeEquivalentTo("4", "5");
    }

不可能知道lambda的第一个参数应该是什么。lambda必须返回IObservable,但是有无限多的类型observable可以实现这一点。

问题是,无法使用lambda表达式从参数推断类型U

可以通过在其他位置指定表达式类型来绕过,如下所示:

Func<IObservable<int>, IObservable<int>> wrapper = o => o.Where(k => k > 3);
var obs = s.Wrap(wrapper);
还是这个

private IObservable<int> Wrapper(IObservable<int>> o)
{
    return o.Where(k => k > 3);
}

var obs = s.Wrap(this.Wrapper);
您还可以通过创建一个不同的重载来绕过它,该重载可以从以下参数推断:

public static IObserver<T> Wrap<T>
    ( this IObserver<T> This
    , Func<IObservable<T>, IObservable<T>> fn )
{
    return This.Wrap<T, T>(fn);
}

var obs = s.Wrap(observer => observer.Where(k => k > 3));

当然,在这种情况下,这只在参数类型和返回类型相同时才起作用。

问题在于lambda中的观察者可以是任何类型。如果要使用不能转换类型的LINQ运算符,可以执行以下操作:

public static IObserver<T> Wrap<T> (this IObserver<T> this, 
    Func<IObservable<T>, IObservable<T>> fn)
{
    var s = new Subject<T>();
    fn(s).Subscribe(this);
    return s;
}
var obs = s.Wrap((IObserver<int> observer) => observer.Where(k => k > 3));