11

我有以下扩展方法MessageBus

public static class MessageBusMixins
{
    public static IDisposable Subscribe<T>(
        this IObservable<T> observable,
        MessageBus bus)
    where T:class
    {
        ...
    }

    public static IDisposable Subscribe<T>( 
        this IObservable<Maybe<T>> observable,
        MessageBus bus)
    {
        ...
    }
}

编译得很好。但是,当我尝试使用它时:

IObservable<Maybe<string>> source = ...;
MessageBus bus = ...;

source.Subscribe(bus);

我得到两个候选方法都不是最具体的错误。但是我认为这Maybe<T>会比这具体T还是不正确?

编辑

它变得更好奇,因为如果我显式调用扩展方法:

MessageBus.SubscribeTo(source, bus);

然后它工作并选择正确的方法。

4

1 回答 1

9

好吧,您可以通过指定类型参数来修复它:

source.Subscribe<string>(bus);

...因为现在只有第二种方法适用。

否则,编译器可以调用以下任一项:

source.Subscribe<string>(bus);
source.Subscribe<Maybe<string>>(bus);

如果您认为第一个比第二个更具体,则必须在 C# 规范中找到这样说的规则:) 这不是不合理的期望,但我认为正常的“更具体”转换不适用于类型参数以及常规参数。

例如,在 C# 4 规范(“Better Function Member”)的第 7.5.3.2 节中,有一条规则:

  • 否则,如果 M P具有比 M Q更具体的参数类型,则 M P比 M Q更好。[...很多关于更少/更具体的细节......]

...但是关于类型参数没有类似的观点。(关于普通参数的第二个讨论类型参数,但那是在参数类型本身之内。)

另一种选择是简单地给方法不同的名称。他们的行为有细微的不同吗?如果是这样,为什么不通过命名让它变得非常明显呢?您真的不希望某人仅仅因为他们对调用哪个重载感到惊讶而做出错误的行为。

于 2012-12-13T08:37:47.743 回答