2009-08-26 31 views
4

C++バックグラウンドから来て、慣れるのに少し難しいC#のオブジェクトのクローニングが見つかりました。私の混乱を解決するために、基底型のオブジェクトを派生型にクローン化するエレガントな方法を探しています。 - 好ましくは、手動でそれらを割り当てずに派生参照型へのC#参照型のクローニング

public class Base 
{ 
    public string Member1; 
    public int Member2; 
    public float Member3; 
    public bool Member4; 
} 

public class Derived : Base 
{ 
    public List<Base> Children; 
} 

Base base = new Base(); 

ということで、私は基本オブジェクトのmemberwiseのコピーをやっている間、「派生」のインスタンスを作成したいの:説明するために

注:これは値型に適しているのでしょうか?

+0

は私に、行うには奇妙なことのように思えます。より多くの文脈を提供するための注意? – Noldorin

答えて

4

あなたがオブジェクトの種類を変更することはできませんので、あなたはいくつかのオプションがあります。

  • カプセル化Base
  • Base
  • からコピーした値がプロパティをコピーコンストラクタを使用しますBaseから反射などまで

後者の場合は012カプセル化のための

Base b= ... 
Derived item = PropertyCopy<Derived>.CopyFrom(b); 

:便利なツールを持っている

public class Derived 
{ 
    readonly Base b; 
    public Derived(Base b) {this.b=b;} 
    public List<Base> Children; 
    public string Member1 {get {return b.Member1;} set {...} } 
    public int Member2 {etc} 
    public float Member3 {etc} 
    public bool Member4 {etc} 
} 

または手動コピーとして

public class Derived : Base 
{ 
    public Derived(Base b) { 
     this.Member1 = b.Member1; 
     // etc 
    } 
    // additional members... 
} 

または(コメント)自身をコピーするためにベースを取得する:

public class Derived : Base 
{ 
    public Derived(Base b) : base(b) { } 
    // additional members... 
} 
public class Base 
{ 
    // members not shown... 
    public Base() {} 
    protected Base(Base b) { 
     this.Member1 = b.Member1; 
     // etc 
    } 
    // additional members... 
} 

BaseのコンストラクタはBaseからフィールドを初期化します)

+0

コピーコンストラクタを使って "手動コピー"バージョンを改善することができます。この方法で、 'Base'に自身のコピーを作成するように頼むことができます。また必要に応じて秘密鍵で再生できます。それからの1つの派生クラスよりも。 –

+0

MiscUtilはまさに私が必要なものです。ありがとうございます。 – Ryall

2
/// Clone all fields from an instance of base class TSrc into derived class TDst 
public static TDst Clone<TSrc, TDst>(TSrc source, TDst target) 
    where TDst : TSrc 
{ 
    var bf = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; 
    foreach (FieldInfo fis in source.GetType().GetFields(bf)) 
     fis.SetValue(target, fis.GetValue(source)); 
    return target; 
} 

/// Create a new instance of a derived class, cloning all fields from type TSrc 
public static TDst Clone<TSrc, TDst>(TSrc source) 
    where TDst : TSrc, new() 
{ 
    return Clone(source, new TDst()); 
}