0

オーバーライドされる仮想メソッドがある単純なクラス階層があります。しかし、特定のコールサイトでは、仮想メソッドではなく、このメソッドの基本クラス バージョンを呼び出したいと考えています。

例えば:

public class A {
    public virtual void Foo() {...}
}

public class B : A {
    public override void Foo() {...}
}

public class Program {
    public void SomeMethod()
    {
       ...

       //  ListofA is type IEnumerable<A>
       foreach (var item in ListofA)
       {
           // I want this to call A.Foo(), rather than B.Foo()
           // But everything I've tried, which has really just been casting, has resulted in B.Foo()
           item.Foo();
       }
    }
}
4

8 に答える 8

8

オーバーライドはできません。オーバーライドは、(呼び出し元の観点から) オリジナルを置き換えます。オーバーライドされたメソッドはベースを呼び出すことができますが、外部から呼び出すことはできません。

于 2011-03-10T20:34:20.003 に答える
3

@ジェームズは正しいです。彼の答えに基づいて、オーバーライドされたバージョンからベース バージョンを呼び出すことができるため、何らかのフラグをメソッドに送信して、独自の実装を実行するか、オーバーライドされたバージョンを実行するかを伝えることができます。このようなもの:

public override void Foo(bool useBaseImplementation)
{
    if(useBaseImplementation)
    {
        base.Foo(useBaseImplementation);
    }
    else
    {
        //other stuff here
    }
}

それが機能するためには、フラグをベースフラグのパラメーターとしても持つ必要がありますが、そこでは無視することができます。エレガントではなく、実に醜いかもしれませんが、探しているものを実行します。

于 2011-03-10T20:39:00.370 に答える
1

この場合、必要なのは実際にはオーバーライドではありません。設計を再考する必要があります。代わりに再定義でoverride使用するnewと、メソッドはポリモーフィックになりませんが、これは設計に欠陥があることを強く示しています。あなたも必要になるでしょうforeach (A item in ListofA)

于 2011-03-10T20:37:58.207 に答える
1

私は私の解決策が好きではありません。なぜなら、それはアブストレーションを醜くするからですが、おそらく次のことができます:

public class A {
  public virtual void Foo() {...}
}

public class B : A {
  public override void Foo() {...}
  public override void parentFoo(){
    base.Foo();
  }
}

public class Program {
  public void SomeMethod(){
    ...

     //  ListofA is type IEnumerable<A>
     foreach (var item in ListofA){
       item.Foo(); //calls B.Foo()
       item.parentFoo(); //calls B.parentFoo() == A.Foo()
     }
  }
}
于 2011-03-10T20:43:51.543 に答える
0

の場合var item = new A()、 を呼び出しますA.Foo()

于 2011-03-10T20:35:40.603 に答える
0

クラス内のキーワードを使用して基本実装を呼び出すことができますbaseが、他のクラスから呼び出しようとしている場合は、コード内のリスコフ置換原則に違反していると確信しています。サブクラスはそのような実装を仮想メソッドに提供する必要があるためです。スーパークラスを完全に置き換えることができます。あなたのデザインを見直してください。

于 2011-03-10T20:38:06.560 に答える
0

override ではなく new を使用してそれを実現できます。ここで非常によく説明されています:http://msdn.microsoft.com/en-us/library/ms173153%28v=vs.80%29.aspx

于 2011-03-10T20:40:59.740 に答える
0

考えられる回避策の 1 つは、メソッドを virtual にせず、 new キーワードを使用して置き換えることです。

   class Program
{
    static void Main(string[] args)
    {
        List<A> list = new List<A>
        {
            new B(),
            new B(),
            new B(),
            new B()
        };

        foreach (A a in list)
        {
            a.Foo();
        }

        foreach (B b in list)
        {
            b.Foo();
        }

        Console.ReadLine();
    }
}

public class A
{
    public void Foo()
    {
        Console.WriteLine("Base");
    }
}

public class B : A
{
    public new void Foo()
    {
        Console.WriteLine("Derived");
    }
}

これは、使用する参照が type の場合にのみ B.Foo() 実装を呼び出しますBnewキーワードが理にかなっている状況に遭遇したことがないので、これを行うことはお勧めしません.

于 2011-03-10T20:43:00.027 に答える