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);

2つの候補メソッドのどちらも最も具体的ではないというエラーが表示されます。しかし、私はそれMaybe<T>より具体的であると思いましたか、Tそれとも正しくありませんか?

編集

拡張メソッドを明示的に呼び出すと、次のようになります。

MessageBus.SubscribeTo(source, bus);

次に、それは機能し、正しい方法を選択します。

4

1 に答える 1

9

タイプ引数を指定することで修正できます。

source.Subscribe<string>(bus);

...現在は 2 番目の方法のみが適用されるためです。

それ以外の場合、コンパイラは次のいずれかを呼び出す可能性があります。

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

最初のほうが 2 番目よりも具体的であると思われる場合は、C# 仕様でそのように記述されたルールを見つける必要があります :) それは不当な期待ではありませんが、通常の「より具体的な」変換が適用されるとは思いません型パラメータと通常のパラメータ。

たとえば、C# 4 仕様 ("Better Function Member") のセクション 7.5.3.2 には、次のルールがあります。

  • それ以外の場合、M Pが M Qよりも具体的なパラメーター タイプを持つ場合、 M Pは M Qよりも優れています。[...あまり具体的でない/より具体的な詳細についての多くの...]

...しかし、型パラメーターについては同様の点はありません。(2 番目の通常のパラメーターについては、型引数について説明していますが、それはパラメーターの型自体の中にあります。)

もう 1 つの方法は、単にメソッドに別の名前を付けることです。彼らは微妙に異なる行動をしていますか?もしそうなら、ネーミングでそれを本当に明白にしてみませんか?どのオーバーロードが呼び出されたかに驚いたという理由だけで、誰かが間違った動作をすることを本当に望んでいません。

于 2012-12-13T08:37:47.743 に答える