57

次のコードで、クラスAのバージョンのメソッドXを呼び出す方法はありますか?

class A
{
  virtual void X() { Console.WriteLine("x"); }
}

class B : A
{
  override void X() { Console.WriteLine("y"); }
}

class Program
{
  static void Main()
  {
    A b = new B();
    // Call A.X somehow, not B.X...
  }

6 답변


95

C#言語の構成要素を使用して、から基本関数を明示的に呼び出すことはできません。外側の範囲AまたはB。あなたが本当にそれをする必要があるならば、それからあなたの設計に欠陥があります - すなわちその機能は最初は仮想であるべきではないか、またはベース機能の一部は別の非仮想機能に抽出されるべきです。

からすることができます内部B.XしかしA.Xを呼び出す

class B : A
{
  override void X() { 
    base.X();
    Console.WriteLine("y"); 
  }
}

しかしそれは別のことです。

Sasha Trufが指摘するようにこの答え、あなたはILを介してそれを行うことができます。 mhandがコメントで指摘しているように、あなたはおそらく反射を通してそれを達成することもできます。


  • (こんにちは。レコードのために、誰かが私が追加した'愚かなトリックのタグを削除し、それから他の誰かがそれを指摘しているコメントを削除しました。人々がSOでやりたいと思うようなダムな編集について知らされるのに役立つでしょう。) - mackenir
  • Bの内側からA.X()を呼び出すことは、オーバーライドされた後にそれを呼び出す必要があることさえ私が知ることができる唯一の状況です。基本クラスのメンバーを持つcopyメソッドがあり、それをオーバーライドして新しいメンバーのコピー機能を追加し、その中でbase.copy()を呼び出すと、すべてがコピーされるとします。 - steviesama
  • 興味深いことに、私はそれがリフレクションを介して達成されることができると思いましたか? - mhand
  • テストを書くとき、多態的なトリックを通して振る舞いを変えたいのは珍しいことではありません。そのため、オーバーライドされたメソッド内から基本メソッドを呼び出す必要があるということは、必ずしも悪い設計を示すわけではありません - それはテストが難しい設計を示している可能性があります。そのようなニーズのせいで、私はあなたの答えに出会いました。 - Pétur Ingi Egilsson
  • @ Pé turIngiEgilsson - 「上書きされたメソッド内から基本メソッドを呼び出す」と書いた場合、そこに書いたものと、そこから基本メソッドを呼び出していたOPに違いがあると思います。外側派生クラス私があなたのコメントを理解したように、あなたはからメソッドを呼び出すことについて話しています。内部派生クラス、これは私が指摘することが可能です。 - Pete

11

C#ではできませんが、MSILは編集できます。

あなたのILコードメイン方法:

.method private hidebysig static void Main() cil managed
{
    .entrypoint
    .maxstack 1
    .locals init (
        [0] class MsilEditing.A a)
    L_0000: nop 
    L_0001: newobj instance void MsilEditing.B::.ctor()
    L_0006: stloc.0 
    L_0007: ldloc.0 
    L_0008: callvirt instance void MsilEditing.A::X()
    L_000d: nop 
    L_000e: ret 
}

L_0008のオペコードはCallvirtコール

L_0008: call instance void MsilEditing.A::X()


9

できません、できません。それがポリモーフィズムの目的であり、各オブジェクトは独自の方法で「基本」のことを実行します。


8

できますが、指定した時点ではできません。のコンテキスト内でB、あなたが呼び出すことができますA.X()電話でbase.X()


4

私は今、歴史の問題だと知っています。しかし、他のグーグルにとっては:あなたはこのようなものを書くことができます。しかし、これには基本クラスの変更が必要であり、外部ライブラリでは使用できなくなります。

class A
{
  void protoX() { Console.WriteLine("x"); }
  virtual void X() { protoX(); }
}

class B : A
{
  override void X() { Console.WriteLine("y"); }
}

class Program
{
  static void Main()
  {
    A b = new B();
    // Call A.X somehow, not B.X...
    b.protoX();


  }


2

メソッドが派生クラスで次のように宣言されている場合は不可能です。overrides。そのためには、派生クラスのメソッドを次のように宣言する必要があります。new

public class Base {

    public virtual string X() {
        return "Base";
    }
}
public class Derived1 : Base
{
    public new string X()
    {
        return "Derived 1";
    }
}

public class Derived2 : Base 
{
    public override string X() {
        return "Derived 2";
    }
}

Derived1 a = new Derived1();
Base b = new Derived1();
Base c = new Derived2();
a.X(); // returns Derived 1
b.X(); // returns Base
c.X(); // returns Derived 2

フィドルはこちら

リンクされた質問


関連する質問

最近の質問