3

TemplateA型のパラメーターを使用してEntryPointを呼び出すと、最初のオーバーロードが常に呼び出されるため、常に例外が発生します。
私が予想したことは、動的バインディングのために最も具体的なメソッド(2番目のオーバーロード)が呼び出されることです。
なぜ何かアイデアはありますか?

private object _obj;
    public void EntryPoint(object p)
    {
        myFunc(p);
    }

    //first overload
    private void myFunc(object container)
    {
        throw new NotImplementedException();
    }

    //second overload
    private void myFunc(TemplateA template)
    {
        _obj = new ObjTypeA(template);
    }

    //third overload
    private void myFunc(TemplateB template)
    {
        _obj = new ObjTypeB(template);
    }
4

4 に答える 4

4

私が予想していたのは、動的バインディングにより、最も具体的なメソッド (2 番目のオーバーロード) が呼び出されることです。

ここで動的バインディングはどこに表示されますか? 変数の静的型はobject. 仮想メソッド直接呼び出さない限り、動的ディスパッチは発生しません。オーバーロードは、コンパイル時に完全に静的に解決されます。

Eric Lippert には、これに関する関連ブログ エントリがあります: Double Your Dispatch, Double Your Fun .

于 2009-07-26T07:02:38.087 に答える
2

EntryPoint()type のパラメーターで呼び出すと、TemplateAにキャストされますobject。したがって、後続の静的にバインドされた への呼び出しmyFunc(p)は、 type のパラメーターを使用して行われますobject

于 2009-07-26T07:04:22.263 に答える
1

dynamicの代わりにを使用すると、C# 4.0 でこれを行うことができますobject。試してみたい場合は、Visual Studio 2010 Beta をダウンロードしてください。それまでは、コンパイラは、パラメーターのコンパイル時の型に基づいて、呼び出すメソッドを正確に選択します。

あなたの例の問題を解決するので、通常のシングルディスパッチポリモーフィズムについて知っているかどうかは、あなたの質問からは明らかではありません。

class TemplateBase
{
    public virtual object MyFunc()
    {
        throw new NotImplementedException();
    }
}

class TemplateA : TemplateBase
{
    public override object MyFunc()
    {
        return new ObjTypeA(this);
    }
}

class TemplateB : TemplateBase
{
    public override object MyFunc()
    {
        return new ObjTypeB(this);
    }
}

そして他の場所:

private object _obj;

public void EntryPoint(TemplateBase p)
{
    _obj = p.MyFunc();
}

TemplateNクラスを変更できない場合の代替手段があります。最も単純なのは、メソッドがデリゲートからのマッピングEntryPointにアクセスできるようにすることです。DictionaryType

Dictionary<Type, Func<object, object>> _myFuncs;

_myFuncs.Add(typeof(TemplateA), o => new ObjTypeA((TemplateA)o));
_myFuncs.Add(typeof(TemplateB), o => new ObjTypeB((TemplateA)o));

次に、渡されたオブジェクトのタイプを実行するデリゲートを検索できます。

Func<object, object> f = _myFuncs[p.GetType()];
_obj = f(p);

ただし、仮想関数の動作を正確に模倣したい場合は、継承階層に注意する必要があります。

于 2009-07-26T08:36:37.770 に答える
0

EntryPoint コンテキストでは、動的ではなく静的バインディングであるため、コンパイラは最初のオーバーロードを呼び出す必要があることを認識していると思います

于 2009-07-26T07:05:41.590 に答える