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

时间:2012-12-13 08:33:15

标签: 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)
    {
        ...
    }
}

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

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

source.Subscribe(bus);

我得到的错误是两种候选方法都没有 最具体。但是我认为Maybe<T>会 是更多特定于T还是不正确?

修改

如果我调用扩展方法,它会变得很糟糕 明确地说:

MessageBus.SubscribeTo(source, bus);

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

1 个答案:

答案 0 :(得分:9)

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

source.Subscribe<string>(bus);

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

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

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

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

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

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

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

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