2

以下のコード行を呼び出すと、ClassBからGet()が実行されます。

オブジェクトは、キーワードClassCを持つメソッドとして、として作成されます。new理想的には、Get()から呼び出す必要がありますClassC

Main()
{
      ClassA obj = new ClassC();
      lbl.Text = obj.Get();
}


public class ClassA
{
  public virtual string Get()
  {
    return "from A";
  }
}

public class ClassB : ClassA
{
  public override string Get()
  {
    return "from B";
  }
}

public class ClassC : ClassB
{
  public new string Get()
  {
    return "from C";
  }
}

誰かが理由を見つけるのを手伝ってくれませんか。

4

7 に答える 7

3

キーは のnewキーワードClassCです。ClassCオブジェクトが として処理される場合、元の関数を覆い隠すためにコンパイラがそれを使用するように指示しGet()ます。

オブジェクトがClassA参照の場合、Get()はオリジナルとして処理されるGet()ため、 でオーバーライドGet()されClassBます。

于 2012-08-27T13:08:00.963 に答える
1

魔法は仮想ディスパッチと呼ばれます。

ClassBをオーバーライドします。これは、 の実装が異なる子孫を持つClassA Getをシステムが認識していることを意味します。タイプ の参照で が呼び出されると、その参照が実際に か子孫かをチェックし、代わりにそのコードを実行します。ClassAGetGetClassAClassB

もちろん、これは(ちょっと)再帰的であるため、オーバーライドした子孫がある場合ClassBGetそれらGetの子孫が呼び出されます...

ここでの問題は、Get定義された inが in で参照されているものとClassC同じGetではなく、完全に新しいメソッド (したがってキーワード) であり、たまたま同じ名前を持っていることです。ClassAClassBnew

そのため、obj.Get()が呼び出されると、システムはそこまでは行かず、そこまで到達して実行するClassCだけです。ClassB実行したい場合は、をにClassC.Get()変更するかnew、次のように参照overrideを介して呼び出すことができますClassC((ClassC)obj).Get()

于 2012-08-27T13:15:56.837 に答える
1

にはClassC.Get異なる署名 (新しい文字列) があり、オーバーライドがないため、オーバーライドしませんClassA.Get

于 2012-08-27T13:08:11.677 に答える
0

newこのコンテキストのキーワードはハイダーです..

これは通常、基本クラスに仮想メソッドがあり、上書きせずに基本クラスの仮想メソッド名と同じ名前が必要な場合に使用されます。

基本クラスのメソッドと new キーワードをオーバーライドせずに派生クラスでそのようなメソッドを宣言すると、コンパイラはWARNINGを生成します。

修飾子を使用しない場合new、コンパイラは警告を生成します。

新しい修飾子は、重複したメンバーは偶然ではなく、したがってコンパイラは警告を表示しないことをコンパイラに伝えます

于 2012-08-27T13:16:11.107 に答える
0

最初に ClassA にキャストしない場合にのみ、ClassC から Get() を呼び出します。Get() の最後の仮想実装は ClassB からの Get() であり、A から仮想 Get() メソッドを呼び出すときに呼び出されます。

于 2012-08-27T13:09:21.137 に答える
0

newキーワードは、継承されたメソッドを隠します。ただし、オブジェクトのコンパイル時の型が type の場合にのみそうしますClassC。あなたの場合、コンパイル時のタイプはClassA、継承されたバージョンの使用につながります。

newこれが、キーワードを使用して継承されたメンバーをシャドウする前に、十分に検討する必要がある理由の 1 つです。インスタンスを保持する変数の宣言された型に応じて、さまざまなメソッドが呼び出される場合があります。

ClassA a = new ClassC();
ClassC c = (ClassC)a; // Note, this is the SAME instance as in a
Assert.AreSame(a, c);

Console.WriteLine(a.Get()); // prints "from B"
Console.WriteLine(c.Get()); // prints "from C"
于 2012-08-27T13:09:50.213 に答える
0

まず、override と new を使用したバージョニングをご覧ください。ClassA参照はGet()元のクラスから処理されます。この型はオーバーライドされているため、の Get()ClassBが呼び出されます。

ClassCreference は新しいGet()メソッドとして処理されるため、メソッド inが呼び出されますClassC

static void Main(string[] args)
{
     ClassA obj = new ClassC(); 
     Console.WriteLine(obj.Get());  // will print out "from B"

     ClassC obj2 = new ClassC(); 
     Console.WriteLine(obj2.Get());  // will print out "from C"
}
于 2012-08-27T13:18:23.680 に答える