C#泛型扩展方法的专业化

bra*_*ing 11 c# generics extension-methods

我有以下扩展方法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)
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

编译好.但是,当我尝试使用它时:

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

source.Subscribe(bus);
Run Code Online (Sandbox Code Playgroud)

我得到的错误是两种候选方法都不是最具体的.不过,我认为Maybe<T>不是具体的T或者是不正确的?

编辑

它变得很糟糕,因为如果我明确地调用扩展方法,那么:

MessageBus.SubscribeTo(source, bus);
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*eet 9

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

source.Subscribe<string>(bus);
Run Code Online (Sandbox Code Playgroud)

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

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

source.Subscribe<string>(bus);
source.Subscribe<Maybe<string>>(bus);
Run Code Online (Sandbox Code Playgroud)

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

例如,在C#4规范的第7.5.3.2节("更好的功能成员")中,有一条规则:

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

...但是关于类型参数没有类似的观点.(关于正常参数的第二个讨论类型参数,但这是参数类型本身.)

另一种方法是简单地给方法赋予不同的名称.他们的行为有微妙的不同吗?如果是这样,为什么不通过命名使这一点变得非常明显?你真的不希望别人得到错误的行为只是因为他们对调用哪个重载感到惊讶.