4

this同様の StackOverflow question および他の記事によると、C# メソッドはデフォルトで「非仮想」です。これは、派生クラスでそれらをオーバーライドできないことを意味します。

それが本当なら、以下の例で、プロパティが「仮想」としてマークされていなくても、Base クラスから継承する Child クラスにプロパティ LastName を実装する方法を教えてください。Child.LastName プロパティは、基本クラスの同じプロパティを「非表示」(VB「シャドウ」) にしますか? もしそうなら、Child.LastName プロパティでこれを示すために "new" キーワードが使用されないのはなぜですか?

このテスト例は、メソッドと仮想がデフォルトで、LastName プロパティの場合は「オーバーライド」が暗示されていることを示唆しているように見えますが、そうではないことは確かです。

私は何が欠けていますか?

public class BaseClass
{

    private string _FirstName;
    public virtual string FirstName {
        get { return _FirstName; }
        set { _FirstName = value; }
    }

    private string _LastName;
    public string LastName {
        get { return _LastName; }
        set { _LastName = value; }
    }

    public void Go()
    {
        MessageBox.Show("Going at default speed in Base Class");
    }

    public void Go(int speed)
    {
        MessageBox.Show("Going at " + speed.ToString() + " in Base Class");
    }
}


public class Child : BaseClass
{

    public override string FirstName {
        get { return "Childs First  Name"; }
        set { base.FirstName = value; }
    }

    public string LastName {
        get { return "Child's Last Name"; }
        set { base.LastName = value; }
    }

    public void Go()
    {
        MessageBox.Show("Going in Child Class");
    }

    public void Go(int speed)
    {
        MessageBox.Show("Going at " + speed.ToString() + " in Child Class");
    }

}
4

4 に答える 4

4

デフォルトでは、C# のメソッドは仮想ではありません。Child クラスの LastName は、BaseClass から LastName を隠します。私が覚えている限り、このコードはコンパイルすることもできますが、新しいキーワードを使用する必要があることを伝える警告がコンパイラによって提供されます。

于 2013-03-17T19:09:06.053 に答える
3

デフォルトでは非仮想です。

サブクラスはベースのプロパティを隠します。LastName

あなたが書く場合:

BaseClass b = new Child(...);
Console.WriteLine(b.LastName);

基本実装が呼び出されていることがわかります。

上記のコードをコンパイルすると、コンパイラはこれについて警告します。ベースのメンバーを非表示にするメンバーを としてマークするのが標準的な方法newです。

public new string LastName {
    get { return "Child's Last Name"; }
    set { base.LastName = value; }
}

これは非常に一般的な C# プログラミングの面接の質問です:)

于 2013-03-17T19:10:02.183 に答える
2

ポリモーフィズムをよく理解すると、これが明確になります。

ポリモーフィズム (C# プログラミング ガイド)

新しいメンバーで基本クラスのメンバーを非表示にする


派生メンバーに基本クラスのメンバーと同じ名前を付けたいが、仮想呼び出しに参加させたくない場合は、 new キーワードを使用できます。new キーワードは、置き換えられるクラス メンバーの戻り値の型の前に置かれます。次のコードに例を示します。

public class BaseClass
{
    public void DoWork() { WorkField++; }
    public int WorkField;
    public int WorkProperty
    {
        get { return 0; }
    }
}

public class DerivedClass : BaseClass
{
    public new void DoWork() { WorkField++; }
    public new int WorkField;
    public new int WorkProperty
    {
        get { return 0; }
    }
}

非表示の基本クラス メンバーには、派生クラスのインスタンスを基本クラスのインスタンスにキャストすることにより、クライアント コードから引き続きアクセスできます。例えば:

DerivedClass B = new DerivedClass();
B.DoWork();  // Calls the new method.

BaseClass A = (BaseClass)B;
A.DoWork();  // Calls the old method.

派生クラスによる仮想メンバーのオーバーライドの防止


仮想メンバーとそれを最初に宣言したクラスとの間で宣言されたクラスの数に関係なく、仮想メンバーは無期限に仮想のままです。クラス A が仮想メンバーを宣言し、クラス B が A から派生し、クラス C が B から派生する場合、クラス B がそのメンバーのオーバーライドを宣言したかどうかに関係なく、クラス C は仮想メンバーを継承し、それをオーバーライドするオプションがあります。次のコードに例を示します。

public class A
{
    public virtual void DoWork() { }
}
public class B : A
{
    public override void DoWork() { }
}

派生クラスは、オーバーライドをシール済みとして宣言することにより、仮想継承を停止できます。これには、クラス メンバー宣言で override キーワードの前に seal キーワードを配置する必要があります。次のコードに例を示します。

public class C : B
{
    public sealed override void DoWork() { }
}

前の例では、メソッド DoWork は、C から派生したどのクラスに対しても仮想ではなくなりました。C のインスタンスが型 B または型 A にキャストされたとしても、それは依然として仮想です。次の例に示すように、新しいキーワード:

public class D : C
{
    public new void DoWork() { }
}

この場合、D 型の変数を使用して D で DoWork が呼び出されると、新しい DoWork が呼び出されます。タイプ C、B、または A の変数を使用して D のインスタンスにアクセスする場合、DoWork への呼び出しは仮想継承の規則に従い、それらの呼び出しをクラス C の DoWork の実装にルーティングします。

于 2013-03-17T19:16:19.263 に答える
1

さて、あなたはそれを正しく理解しました。仮想でない場合は非表示になります。

キーワードは、継承階層チェーンでのnew仮想オーバーライドにブレーキをかけます。

読むための簡単な例:ポリモーフィズム、C# でのメソッドの非表示とオーバーライド

于 2013-03-17T19:11:27.547 に答える