2

この非常に単純な例は私を混乱させます:

public class X {
    public void XMethod(A a) {
        Console.WriteLine(a.GetType());
        Console.WriteLine("Got A");
    }

    public void XMethod(B b) {
        Console.WriteLine(b.GetType());
        Console.WriteLine("Got B");
    }
}

public abstract class A {
    public virtual void M(X x) {
        Console.WriteLine(this.GetType());
        x.XMethod(this);
    }
}

public class B : A {

}

class Program {
    static void Main(string[] args) {
        X x = new X();
        B b = new B();
        b.M(x);
    }
}

これの出力は

B
B
Got A

「Got A」までは大丈夫です。class のインスタンスでX.XMethod(B)メソッドを呼び出すと、メソッドが呼び出されると思います。MB

ここで何が起こっているのですか?提供された引数の型が であり、 ではないことが明らかな場合、 が呼び出され、 がXMethod(A)呼び出されないのはなぜですか?XMethod(B)BA

PS: 同等の実装のために Java で同じ出力を得ました。

4

3 に答える 3

3

A.MオンメソッドしかありませんAの 1 つと 1 つではありませんB

IL は、A.Mすべてのインスタンスで同じです。はコンパイル時に(または) であることA.Mしか認識thisしていないため、常にに解決されます。このメソッド解決は、コンパイル時に生成された IL にあり、サブクラスでは変更されません (実際、サブクラスは、コンパイラが知らない別のアセンブリにある可能性があります)。AobjectXMethod(A)

.method public hidebysig newslot virtual instance void M(class X x) cil managed
{
    .maxstack 8
    L_0000: ldarg.0 
    L_0001: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
    L_0006: call void [mscorlib]System.Console::WriteLine(object)
    L_000b: ldarg.1 
    L_000c: ldarg.0 
    L_000d: callvirt instance void X::XMethod(class A)
    L_0012: ret 
}

必要な動作を得るには、 を使用できますdynamicただし、そうすべきだと言っているわけではありません。

于 2012-05-14T05:57:07.173 に答える
1

this操作を呼び出している現在のオブジェクトを常に参照しています...あなたの場合、Bメソッドを呼び出したい場合は、仮想操作をオーバーライドする必要があります.

public class B : A {  
public override void M(X x) {
         Console.WriteLine(this.GetType());
         x.XMethod(this);
     } 
} 
于 2012-05-14T05:57:05.137 に答える
0

私は100%確実ではありませんが、2つの可能な型一致でメソッドのオーバーロードを使用する場合は、常に「最も低いもの」が使用されると思います。

編集:hvdのコメントの後、私はそれをチェックしました、そして彼は正しいです:
例えば次の例:

static void Main(string[] args)
{
    string str = "bla";
    object obj = str;

    DoIt(str);
    DoIt(obj);
}

public static void DoIt(object p) { Console.WriteLine("Object!"); }
public static void DoIt(string p) { Console.WriteLine("String!"); }

プリント

弦!
物体!

于 2012-05-14T05:58:14.437 に答える