web-dev-qa-db-ja.com

派生クラスを基本クラスに変換

記憶を更新しようとしていますが、Googleで答えが見つかりません。

public class BaseClass
{
    public virtual void DoSomething()
    {
        Trace.Write("base class");
    }
}

public class DerivedClass : BaseClass
{
    public override void DoSomething()
    {
        Trace.Write("derived class");
    }
}

派生クラスのインスタンスを作成する場合、DoSomething()が呼び出されたときにベースクラスのメソッドのみが使用されるように、それをベースクラスに変換するにはどうすればよいですか?

動的キャストは、派生クラスのオーバーライドされたメソッドを呼び出します。

DerivedClass dc = new DerivedClass();

dc.DoSomething();

(dc as BaseClass).DoSomething();

出力:「派生クラス」

32
Levitikon

それは不可能です-それは完全に意図的なものです。整合性を維持するために、オーバーライドされたメソッドに渡す引数に特定の前提条件を強制する派生クラスがあるとします...その検証をバイパスして内部整合性を破壊することはできません。

クラス自体の中で、base.AnyMethod()を非仮想的に呼び出すことができます(オーバーライドするメソッドであるかどうかは関係ありません)。それが何をしているか。

35
Jon Skeet

これは不合理に聞こえますが、動作しますが

 DerivedClass B = new DerivedClass();

BaseClass bc = JsonConvert.DeserializeObject<BaseClass>(JsonConvert.SerializeObject(B));
36
shazia

絶対にCAN(基本メソッドを呼び出す)を実行できます。ポリモーフィズムを読んでください:

https://docs.Microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/polymorphism

例:

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

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

そして、それを呼び出す方法:

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

BaseClass A = (BaseClass)B;
A.DoWork();  // This calls the old method.
11
Papa Burgundy

newの代わりにoverride keyworを使用してみてください。私が知る限り、これは望ましい動作を可能にするはずです。私はそれについて本当に確信がないので、私が間違っていても私を責めないでください!

public class BaseClass
{
    public virtual void DoSomething()
    {
        Trace.Write("base class");
    }
}

public class DerivedClass : BaseClass
{
    public new void DoSomething()
    {
        Trace.Write("derived class");
    }
}
4
oberfreak

newの代わりにoverrideを使用するソリューションは、ポリモーフィズムを破壊します。最近、私は同じ問題に遭遇し、次のように実装しました。私のソリューションには次の利点があります。

  • virtualおよびoverrideはそのままです。
  • 名前BaseClassは型キャストで直接使用されないため、MiddleClassBaseClassの間の階層に中間DerivedClassを導入すると、DoSomething()も実装します; MiddleClassの実装はスキップされません。

これは実装です:

public class BaseClass
{
    public virtual void DoSomething()
    {
        Trace.Write("base class");
    }
}

public class DerivedClass : BaseClass
{
    public override void DoSomething()
    {
        Trace.Write("derived class");
    }

    public void BaseDoSomething()
    {
        base.DoSomething();
    }
}

使用法は次のとおりです。

    DerivedClass dc = new DerivedClass();

    dc.DoSomething();

    dc.BaseDoSomething();
2
Andrej Adamenko