0

C#でオーバーロードされた(または非表示と呼ぶ必要がある)メソッドの呼び出しについていくつか質問がありました。次のようなクラスがあるとします。

class ParaA {}
class ParaB : ParaA {}
class ParaC : ParaB {}

class TheBaseClass 
{
   public void DoJob (ParaA a){Console.WriteLine ("DoJob in TheBaseClass is being invoked");}

}

class TheDerivedClass : TheBaseClass 
{
  public void DoJob (ParaB b){Console.WriteLine ("DoJob in TheDerivedClass is being invoked");}
}

class Test
{
  //Case 1: which version of DoJob() is being called?
  TheDerivedClass aInstance= new TheDerivedClass ();
  aInstance.DoJob(new ParaA ());

  //Case 2: which version of DoJob() is being called?
  TheBaseClass aInstance= new TheDerivedClass ();
  aInstance.DoJob(new ParaA ());

  //Case 3: which version of DoJob() is being called?
  TheBaseClass aInstance= new TheDerivedClass ();
  aInstance.DoJob(new ParaB ());

  //Case 4: which version of DoJob() is being called?
  TheBaseClass aInstance= new TheDerivedClass ();
  aInstance.DoJob(new ParaC ());

}

自分がやろうとしていることを明確にしたことを願っています。呼び出し元によって提供されたパラメーターがどの署名とも完全に一致しないが、一部の署名と互換性がある場合に、C#が呼び出すメソッドの「一致した」バージョンをどのように検索するかを知りたいです。メソッドがクラス内でオーバーロードされるだけでなく、派生クラスによって非表示、オーバーライド、またはオーバーロードされると、さらに混乱します。上記の例は、考えられるすべてのシナリオを網羅しているわけではありません。これには何か用語がありますか?

よろしくお願いします!

マシュー

4

2 に答える 2

0

Case2-4TheBaseClassは、DoJobが仮想メソッドではなく、タイプがであるという理由だけでaInstance呼び出しTheBaseClassます。

TheBaseClassCase1は、直接一致するために呼び出されます。

于 2012-07-12T03:52:02.137 に答える
0

コードをコンパイルするために、さらに数行追加しました。

void Main()
{
    var t = new Test();
    t.Run();
}
class ParaA {}
class ParaB : ParaA {}
class ParaC : ParaB {}

class TheBaseClass 
{
   public void DoJob (ParaA a){Console.WriteLine ("DoJob in TheBaseClass is being invoked");}

}

class TheDerivedClass : TheBaseClass 
{
  public  void DoJob (ParaB b){Console.WriteLine ("DoJob in TheDerivedClass is being invoked");}
}

public class Test
{
    public void Run()
    {
        //Case 1: which version of DoJob() is being called?
        TheDerivedClass aInstance= new TheDerivedClass ();
        aInstance.DoJob(new ParaA ());

        //Case 2: which version of DoJob() is being called?
        TheBaseClass aInstance2= new TheDerivedClass ();
        aInstance2.DoJob(new ParaA ());

        //Case 3: which version of DoJob() is being called?
        TheBaseClass aInstance3= new TheDerivedClass ();
        aInstance3.DoJob(new ParaB ());

        //Case 4: which version of DoJob() is being called?
        TheBaseClass aInstance4= new TheDerivedClass ();
        aInstance4.DoJob(new ParaC ());
    }
}

は次の出力を生成します。

DoJob in TheBaseClass is being invoked
DoJob in TheBaseClass is being invoked
DoJob in TheBaseClass is being invoked
DoJob in TheBaseClass is being invoked

つまり、基本クラスのメソッドは毎回呼び出されます。

ケース1では、引数がParaAであり、ParaAがParaBではないために呼び出されます。それ以外の場合は、オブジェクトインスタンスのタイプが「TheBaseClass」であるために呼び出されます。

メソッドのオーバーロードを説明するために変更された同じコードを次に示します。

void Main()
{
    var t = new Test();
    t.Run();
}

class ParaA {}
class ParaB : ParaA {}
class ParaC : ParaB {}

class TheBaseClass 
{
   public virtual void DoJob (ParaA a){Console.WriteLine ("DoJob in TheBaseClass is being invoked");}

}

class TheDerivedClass : TheBaseClass 
{
  public override void DoJob (ParaA b){Console.WriteLine ("DoJob in TheDerivedClass is being invoked");}
}

public class Test
{
    public void Run()
    {
        //Case 1: which version of DoJob() is being called?
        TheDerivedClass aInstance= new TheDerivedClass ();
        aInstance.DoJob(new ParaA ());

        //Case 2: which version of DoJob() is being called?
        TheBaseClass aInstance2= new TheDerivedClass ();
        aInstance2.DoJob(new ParaA ());

        //Case 3: which version of DoJob() is being called?
        TheBaseClass aInstance3= new TheDerivedClass ();
        aInstance3.DoJob(new ParaB ());

        //Case 4: which version of DoJob() is being called?
        TheBaseClass aInstance4= new TheDerivedClass ();
        aInstance4.DoJob(new ParaC ());
    }
}

出力は次のようになります。

DoJob in TheDerivedClass is being invoked
DoJob in TheDerivedClass is being invoked
DoJob in TheDerivedClass is being invoked
DoJob in TheDerivedClass is being invoked

オブジェクトのタイプが「TheDerivedClass」であるため、DerivedClassメソッドは毎回呼び出されます。

于 2012-07-12T03:58:20.613 に答える