Visual Studio 2013中的C#方法重载解析问题

时间:2018-04-20 09:52:38

标签: c# rx.net

在Rx.NET库中提供这三种方法

public static IObservable<TResult> Create<TResult>(Func<IObserver<TResult>, CancellationToken, Task> subscribeAsync) {...}
public static IObservable<TResult> Create<TResult>(Func<IObserver<TResult>, CancellationToken, Task<IDisposable>> subscribeAsync) {...}
public static IObservable<TResult> Create<TResult>(Func<IObserver<TResult>, CancellationToken, Task<Action>> subscribeAsync) {...}

我在 MSVS 2013

中编写以下示例代码
var sequence =
  Observable.Create<int>( async ( observer, token ) =>
                          {
                            while ( true )
                            {
                              token.ThrowIfCancellationRequested();
                              await Task.Delay( 100, token );
                              observer.OnNext( 0 );
                            }
                          } );

由于模糊的重载,这不会编译。编译器的确切输出是:

Error    1    The call is ambiguous between the following methods or properties: 
'System.Reactive.Linq.Observable.Create<int>(System.Func<System.IObserver<int>,System.Threading.CancellationToken,System.Threading.Tasks.Task<System.Action>>)' 
and 
'System.Reactive.Linq.Observable.Create<int>(System.Func<System.IObserver<int>,System.Threading.CancellationToken,System.Threading.Tasks.Task>)'

但是,只要我将while( true )替换为while( false )var condition = true; while( condition )...

var sequence =
  Observable.Create<int>( async ( observer, token ) =>
                          {                            
                            while ( false ) // It's the only difference
                            {
                              token.ThrowIfCancellationRequested();
                              await Task.Delay( 100, token );
                              observer.OnNext( 0 );
                            }
                          } );

错误消失,方法调用解析为:

public static IObservable<TResult> Create<TResult>(Func<IObserver<TResult>, CancellationToken, Task> subscribeAsync) {...}

那里发生了什么?

1 个答案:

答案 0 :(得分:5)

除了@Daisy Shipton的答案之外,我想补充一点,在以下情况中也可以观察到同样的行为:

var sequence = Observable.Create<int>(
    async (observer, token) =>
    {
        throw new NotImplementedException();
    });

基本上是因为同样的原因 - 编译器看到lambda函数永远不会返回,所以任何返回类型都匹配,这反过来使lambda匹配任何Observable.Create重载。

最后,一个简单解决方案的示例:您可以将lambda转换为所需的签名类型,以提示编译器选择哪个Rx重载。

var sequence =
    Observable.Create<int>(
        (Func<IObserver<int>, CancellationToken, Task>)(async (observer, token) =>
        {
            throw new NotImplementedException();
        })
      );