我有以下C#擴展方法的IObserver。它使我能夠通過使用中間主題將LINQ表達式放在頭上。有沒有辦法解決這個C#類型推斷失敗?
/// <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");
}
這是不可能知道observable
的第一個參數的拉姆達應該的。 lambda必須返回IObservable,但有無數個可觀察類型可以實現此目的。