Visual Studio 2013中C#方法重载解析问题:Rx.NET Create方法重载疑问
解决Rx.NET Create方法的重载解析问题
我之前也碰到过这个棘手的重载匹配问题,这三个Create方法的签名实在太像了——都是接受一个Func<IObserver<TResult>, CancellationToken, TaskXXX>类型的委托,区别只在Task的返回类型。编译器没法自动推断你的lambda到底对应哪一个重载,所以得给它点“提示”才行。下面是几个靠谱的解决办法:
方法1:明确指定lambda的返回类型
让编译器一眼就能看出来你的lambda返回的是Task、Task<IDisposable>还是Task<Action>,比如:
匹配返回Task的重载
Observable.Create<string>(async (observer, ct) => { observer.OnNext("Hello"); await Task.Delay(1000, ct); observer.OnCompleted(); // 这里不需要返回任何值,编译器会推断为Task });
或者如果你不使用async/await,直接返回Task.CompletedTask:
Observable.Create<string>((observer, ct) => { observer.OnNext("Hello"); observer.OnCompleted(); return Task.CompletedTask; });
匹配返回Task<IDisposable>的重载
明确返回一个IDisposable实例,编译器会自动包装成Task<IDisposable>:
Observable.Create<int>(async (observer, ct) => { var subscription = SomeOtherObservable.Subscribe(observer); await Task.Delay(5000, ct); return subscription; // 返回IDisposable,对应第二个重载 });
匹配返回Task<Action>的重载
返回一个Action类型的清理逻辑,用Task.FromResult包装:
Observable.Create<long>(async (observer, ct) => { var timer = new Timer(_ => observer.OnNext(DateTime.Now.Ticks)); timer.Start(); return Task.FromResult<Action>(() => timer.Dispose()); // 返回Task<Action>,对应第三个重载 });
方法2:显式转换委托类型
如果你的lambda逻辑比较复杂,返回类型不够明显,可以直接把lambda转换成对应的Func类型,给编译器明确的指示:
// 明确指定匹配第一个返回Task的重载 Observable.Create<byte[]>( (Func<IObserver<byte[]>, CancellationToken, Task>)async (observer, ct) => { // 你的异步逻辑 await SomeAsyncOperation(ct); } );
为什么会出现这个问题?
C#的重载解析规则里,不会根据委托的返回值来区分重载——这三个Create方法的参数都是泛型委托,参数列表看起来完全一样(都是两个输入参数),只有返回的Task类型不同。当编译器无法从lambda的代码里推断出明确的返回类型时,就会抛出重载模糊的错误。
内容的提问来源于stack exchange,提问作者Mooh
相关产品推荐
相关产品推荐

