8

これは以前に答えられているかもしれません。「動的メソッドのオーバーロードの解決」に関する質問はたくさんありますが、特にdynamic引数の受け渡しに関する質問はありません。次のコードではTest、 への最後の呼び出しMが解決できません (コンパイルされません)。エラーは次のとおりです: [の最初の 2 つのオーバーロード]の間で呼び出しがあいまいMです。

static void M(Func<int> f) { }
static void M(Func<string> f) { }
static void M(Func<dynamic> f) { }

static dynamic DynamicObject() {
    return new object();
}

static void Test() {
    M(() => 0);
    M(() => "");
    M(() => DynamicObject()); //doesn't compile
}
  1. 型が静的に認識されていないため、オーバーロードの受け入れに解決されないのはなぜdynamicですか?
  2. オーバーロードされたメソッドを使用することさえ可能dynamicですか?
  3. これを解決する最善の方法は何ですか?
4

2 に答える 2

5

ここでの問題は型推論です。コンパイラは、引数に基づいて使用するオーバーロードを見つけようとしていますが、選択されたオーバーロードに基づいて引数の型を見つけようとしています。の場合M(() => DynamicObject())、プロセスは次のようになります。

  1. メソッドへの引数は、パラメータがゼロのラムダです。これにより、可能性として 3 つのオーバーロードすべてが得られます。
  2. ラムダの本体が返されますdynamic。から他の型への暗黙的な変換があるため、dynamic3 つのオーバーロードすべてが適切であることがわかります。
  3. 最適なオーバーロードを選択してみてください。ほとんどの場合、「最良」は最も派生した型を意味します。と は両方とも から派生しているため、intと をstring使用しobjectたオーバーロードが最適intstring見なされます。
  4. これで、2 つの "最適な" オーバーロードができました。これは、コンパイラが実際にそれらの 1 つを選択できないことを意味します。コンパイルは失敗します。

さて、あなたの問題に対する可能な解決策について:

  1. キャストまたは型付きローカル変数を使用して、ラムダの型を明示的にします。

    M((Func<dynamic>)(() => DynamicObject()));
    

    また

    Func<dynamic> f = () => DynamicObject();
    M(f);
    
  2. 動的オーバーロードの名前をDynamicM. この方法では、オーバーロードの解決に対処する必要はありません。

  3. これは私にはやや間違っているように感じます:dynamicにキャストすることにより、オーバーロードだけが適合することを確認してくださいobject:

    M(() => (object)DynamicObject())
    
于 2011-08-26T21:00:51.270 に答える
1

MSDN の定義から:

動的

ダイナミック型は、ほとんどの状況でオブジェクト型のように動作します。ただし、dynamic 型の式を含む操作は、コンパイラによって解決または型チェックされません。コンパイラは操作に関する情報をまとめてパッケージ化し、その情報は後で実行時に操作を評価するために使用されます。プロセスの一部として、dynamic 型の変数は object 型の変数にコンパイルされます。したがって、タイプ dynamic は、実行時ではなく、コンパイル時にのみ存在します

したがって、コンパイル時に動的は存在しません。これは、それを宛先の *type* に変換する必要があるためです。そのため、動的を解決できません。宛先タイプとは何ですか?

実際、次のようなことをすると:

static void M(Func<int> f) { }
static void M(Func<string> f) { }
static void M(Func<object> f) { } // could be also declared like dynamic here, works by the way

static object DynamicObject()
{
    return new object();
}

static void Test()
{
    M(() => 0);
    M(() => "");
    M(() => DynamicObject());
}

変換する必要がある型objectの違いで、コンパイル時にすでに型のように存在するため、必要に応じて完全に機能します。dynamic

于 2011-08-26T20:20:49.073 に答える