215

virtual子型で一致するメソッドを宣言するときoverrideに単純に「new

4

11 に答える 11

242

このようなことは、写真を使った方が理解しやすいといつも思っています。

繰り返しますが、ジョセフ・デイグルのコードを使用すると、

public class Foo
{
     public /*virtual*/ bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public /*override or new*/ bool DoSomething() { return true; }
}

次に、次のようなコードを呼び出す場合:

Foo a = new Bar();
a.DoSomething();

注: 重要なことは、オブジェクトは実際にはですBar、型の変数に格納していることですFoo(これはキャストに似ています)。

クラスを宣言するときにvirtual/を使用したoverrideかどうかに応じて、結果は次のようになります。new

Virtual/Override 説明イメージ

于 2008-10-01T22:41:29.277 に答える
192

「new」キーワードはオーバーライドされません。基本クラスのメソッドとは関係のない新しいメソッドを意味します。

public class Foo
{
     public bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public new bool DoSomething() { return true; }
}

public class Test
{
    public static void Main ()
    {
        Foo test = new Bar ();
        Console.WriteLine (test.DoSomething ());
    }
}

これは false を出力します。override を使用すると、true が出力されます。

(基本コードは Joseph Daigle から取得)

したがって、実際のポリモーフィズムを行っている場合は、常に OVERRIDEを使用する必要があります。「new」を使用する必要がある唯一の場所は、メソッドが基本クラスのバージョンにまったく関係がない場合です。

于 2008-10-01T22:10:01.223 に答える
46

仮想メソッドと非仮想メソッドの動作の違いを理解するためのコードを次に示します。

class A
{
    public void foo()
    {
        Console.WriteLine("A::foo()");
    }
    public virtual void bar()
    {
        Console.WriteLine("A::bar()");
    }
}

class B : A
{
    public new void foo()
    {
        Console.WriteLine("B::foo()");
    }
    public override void bar()
    {
        Console.WriteLine("B::bar()");
    }
}

class Program
{
    static int Main(string[] args)
    {
        B b = new B();
        A a = b;
        a.foo(); // Prints A::foo
        b.foo(); // Prints B::foo
        a.bar(); // Prints B::bar
        b.bar(); // Prints B::bar
        return 0;
    }
}
于 2008-10-01T22:15:01.680 に答える
20

このnewキーワードは、実際には、その特定の型にのみ存在する完全に新しいメンバーを作成します。

例えば

public class Foo
{
     public bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public new bool DoSomething() { return true; }
}

メソッドは両方のタイプに存在します。リフレクションを使用して type のメンバーを取得すると、まったく同じように見えるBar2 つのメソッドが実際に呼び出されていることがわかります。DoSomething()を使用newすることで、基本クラスの実装を効果的に非表示にできるため、(私の例では) からクラスが派生するときに、Barへのメソッド呼び出しが にbase.DoSomething()移動し、 に移動BarしませんFoo

于 2008-10-01T22:10:18.150 に答える
11

技術的な詳細だけでなく、仮想/オーバーライドを使用すると、設計に関する多くのセマンティック情報が伝達されると思います。メソッドvirtualを宣言するときは、実装クラスが独自のデフォルト以外の実装を提供することを期待していることを示します。同様に、基本クラスでこれを省略すると、すべての実装クラスに対してデフォルトのメソッドで十分であるという期待が宣言されます。同様に、抽象宣言を使用して、実装クラスに独自の実装を提供させることができます。繰り返しになりますが、これは、プログラマーがコードの使用をどのように期待しているかについて多くのことを伝えていると思います。基本クラスと実装クラスの両方を作成していて、newを使用していることに気付いた場合は、親でメソッドを仮想化しないという決定を真剣に考え直し、自分の意図を具体的に宣言します。

于 2008-10-01T22:20:31.963 に答える
10

virtual / overrideは、2つのメソッドが関連していること、および状況によっては最初の(仮想)メソッドを呼び出していると思われる場合に、代わりに2番目の(オーバーライドされた)メソッドを呼び出すことが実際に正しいことをコンパイラーに通知します。これがポリモーフィズムの基盤です。

(new SubClass() as BaseClass).VirtualFoo()

サブクラスのオーバーライドされたVirtualFoo()メソッドを呼び出します。

newは、基本クラスのメソッドと同じ名前の派生クラスにメソッドを追加しているが、それらは相互に関係がないことをコンパイラーに通知します。

(new SubClass() as BaseClass).NewBar()

BaseClassのNewBar()メソッドを呼び出しますが、次のようになります。

(new SubClass()).NewBar()

サブクラスのNewBar()メソッドを呼び出します。

于 2008-10-01T22:24:02.517 に答える
4

overrideキーワードとnewキーワードの違いは、前者はメソッドのオーバーライドを行い、後者はメソッドの非表示を行うことです。

詳細については、以下のリンクを確認してください...

MSDN および その他

于 2008-10-01T22:11:50.923 に答える
3
  • newキーワードは非表示用です。- 実行時にメソッドを隠していることを意味します。出力は基本クラスのメソッドに基づいています。
  • overrideオーバーライドするため。- 基本クラスの参照を使用して派生クラス メソッドを呼び出していることを意味します。出力は、派生クラス メソッドに基づきます。
于 2011-07-19T06:51:47.620 に答える
1

私のバージョンの説明は、プロパティを使用して違いを理解するのに役立ちます。

override簡単ですよね?基になる型は親の型をオーバーライドします。

newおそらく誤解を招く可能性があります(私にとってはそうでした)。プロパティを使用すると、理解しやすくなります。

public class Foo
{
    public bool GetSomething => false;
}

public class Bar : Foo
{
    public new bool GetSomething => true;
}

public static void Main(string[] args)
{
    Foo foo = new Bar();
    Console.WriteLine(foo.GetSomething);

    Bar bar = new Bar();
    Console.WriteLine(bar.GetSomething);
}

デバッガーを使用すると、実際にはとの 2 つのバージョンのプロパティがあるため、 には 2 つのプロパティがFoo fooあること がわかります。どちらを使用するかを知るために、c# は現在の型のプロパティを "選択" します。GetSomethingFooBar

Bar のバージョンを使用したい場合は、Foo foo代わりに override または use を使用していたでしょう。

Bar barのまったく新しい動作が必要なため、 は1 つしかありません。GetSomething

于 2016-09-06T07:30:48.733 に答える
1

メソッドを何もマークしないということは、実行時型ではなく、オブジェクトのコンパイル型を使用してこのメ​​ソッドをバインドすることです (静的バインディング)。

メソッドを手段でマークvirtualする: コンパイル時の型ではなく、オブジェクトの実行時の型を使用してこのメ​​ソッドをバインドします (動的バインディング)。

virtual基本クラスメソッドをin 派生クラスでマークするoverrideことは、次のことを意味します。これは、オブジェクトのランタイム タイプを使用してバインドされるメソッドです (動的バインディング)。

virtual基本クラスメソッドをin 派生クラスでマークするnewことは、次のことを意味します。これは新しいメソッドであり、基本クラスの同じ名前のメソッドとは関係がなく、オブジェクトのコンパイル時の型 (静的バインディング) を使用してバインドする必要があります。

virtual派生クラスで基本クラス メソッドをマークしないということは、次のことを意味します。このメソッドはnew(静的バインディング) としてマークされます。

メソッドをマークするということは、次のことabstractを意味します。このメソッドは仮想ですが、本体は宣言せず、そのクラスも抽象 (動的バインディング) です。

于 2018-12-05T19:59:34.197 に答える