С# специализация общих методов расширения

У меня есть следующие методы расширения для моего 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

Ну, вы можете исправить это, указав аргумент типа:

source.Subscribe<string>(bus);

... так как теперь применим только второй метод.

В противном случае компилятор мог бы позвонить либо из:

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

Если вы считаете, что первое более конкретное, чем второе, вам нужно найти правило в спецификации С#, которое говорит так:) Это не необоснованное ожидание, но я не думаю, что нормальный "более конкретный", преобразования применяются к параметрам типа, а также к регулярным параметрам.

Так, например, в разделе 7.5.3.2 спецификации С# 4 ( "Лучший член функции" ) существует правило о:

  • В противном случае, если M P имеет более конкретные типы параметров, чем M Q, то M P лучше, чем M Qк югу > . [... много деталей о менее/более конкретных...]

... но нет аналогичной точки о параметрах типа. (Второй о нормальных параметрах говорит о аргументах типа, но в самих параметрах.)

Другой вариант - просто дать методам разные имена. У них тонкое поведение? Если да, почему бы не сделать это действительно очевидным через именование? Вы действительно не хотите, чтобы кто-то искал неправильное поведение только потому, что был удивлен тем, какая перегрузка была вызвана.