4

から派生したクラスAがあるとします。BA

class A : ICloneable
{
    public object Clone() {...}
}

class B : A, ICloneable
{
    public object Clone() {...}
}

を与える

'B.Clone()' hides inherited member 'A.Clone()'. Use the new keyword if hiding was intended.

警告。

(1) 推奨される方法は何ですか? で使用またはnew宣言するA.Clone()_ virtual_overrideB

(2) にいくつかのメンバーがAあり、適切に複製されてA.Clone()いる場合、それらを複製する簡単な方法はありますか、B.Clone()それとも明示的に複製する必要がB.Clone()ありますか?

4

1 に答える 1

9

ソースにアクセスできる場合(ここではそうだと思います)、それを絶対に宣言してvirtualオーバーライドします。ベースCloneを非表示にnewするのは悪い考えかもしれません。で動作していることを知らないコードがあるBと、間違ったクローン メソッドが起動され、適切なクローンが返されません。

プロパティの割り当てに関しては、おそらくコピー コンストラクターの実装を検討してください。各レベルで独自のクローンを処理できます。

    public class A : ICloneable
    {
        public int PropertyA { get; private set; }

        public A()
        {

        }

        protected A(A copy)
        {
            this.PropertyA = copy.PropertyA;
        }

        public virtual object Clone()
        {
            return new A(this);
        }
    }

    public class B : A, ICloneable
    {
        public int PropertyB { get; private set; }

        public B()
        {

        }

        protected B(B copy)
            : base(copy)
        {
            this.PropertyB = this.PropertyB;
        }

        public override object Clone()
        {
            return new B(this);
        }
    }

各コピー コンストラクターは、ベース コピー コンストラクターを呼び出し、それ自体をチェーンに渡します。各継承レベルは、それに属するプロパティを直接コピーします。

編集:newキーワードを使用して基本実装を非表示にする場合、次の例が発生する可能性があります。サンプル実装(一見問題ないように見えます)

public class A : ICloneable
{
    public int PropertyA { get; protected set; }

    public object Clone()
    {
        Console.WriteLine("Clone A called");
        A copy = new A();
        copy.PropertyA = this.PropertyA;
        return copy;
    }
}

public class B : A, ICloneable
{
    public int PropertyB { get; protected set; }

    public new object Clone()
    {
        Console.WriteLine("Clone B called");
        B copy = new B();
        copy.PropertyA = this.PropertyA;
        copy.PropertyB = this.PropertyB;
        return copy;
    }
}

しかし、あなたがそれを使うとき:

B b = new B();
A a = b;
B bCopy = (B)a.Clone();
//"Clone A called" Throws InvalidCastException! We have an A!
于 2012-12-31T16:16:26.987 に答える