从派生类复制基类的内容

我目前有一个派生类和一个基类。 如何使派生类的基类等于我拥有的基类? 浅拷贝会起作用吗?

class Base { private string name; public string Name { get; set; } private string address; public string Address { get; set; } } class Derived:Base { private string field; public String field { get; set; } } namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Base b = new Base(); b.Address = "Iliff"; b.Name = "somename"; Derived d = new Derived(); //How can I make the base class of d equal to b ? } } } 

为基类创建一个复制构造函数,这样你还需要创建一个无参数构造函数,并且通过添加复制构造函数,编译器将不再生成默认构造函数。 然后在派生类中调用基类的复制构造函数。

 public class Base { public int Name { get; set; } public string Address { get; set; } public Base() { } public Base(Base toCopy) { this.Name = toCopy.Name; this.Address = toCopy.Address; } } public class Derived : Base { public String Field { get; set; } public Derived(Base toCopy) : base (toCopy) { } // if desired you'll need a parameterless constructor here too // so you can instantiate Derived w/o needing an instance of Base public Derived() { } } 

如果我理解正确,这将有效:

 class Derived : Base { // all the code you had above, plus this: public Derived(Base toCopy) { this.name = toCopy.name; this.address = toCopy.address; } } Derived d = new Derived(b); 

您必须手动将Base实例的字段复制到新的Derived实例。

这样做的一种常见方法是提供一个复制构造函数:

 public Derived(Base other) { if (other == null) { throw new ArgumentNullException("other"); } this.name = other.name; this.address = other.address; } 

还有一个关于你的代码的说明:

 private string field; public string Field { get; set; } 

这没有多大意义(对于其他属性也是如此)。

public string Field { get; set; } public string Field { get; set; }表示编译器将自动创建一个私有字段。 您的field字段永远不会被使用。

要么只写public string Field { get; set; } public string Field { get; set; } public string Field { get; set; } ,因为将自动创建私有字段。 或者以某种方式声明Field属性,以便使用您的私有字段:

 private string field; public string Field { get { return field; } set { field = value; } } 

另一种方法是将基类映射到派生类:

 ///  /// Maps the source object to target object. ///  /// Type of target object. /// Type of source object. /// Target object. /// Source object. /// Updated target object. public static T Map(this T target, TU source) { // get property list of the target object. // this is a reflection extension which simply gets properties (CanWrite = true). var tprops = target.GetProperties(); tprops.ToList().ForEach(prop => { // check whether source object has the the property var sp = source.GetType().GetProperty(prop); if (sp != null) { // if yes, copy the value to the matching property var value = sp.GetValue(source, null); target.GetType().GetProperty(prop).SetValue(target, value, null); } }); return target; } 

例:

 var derivedClass = new DerivedClass(); derivedClass.Map(baseClass); 

您始终可以使用Object.MemberwiseClone来复制它。

http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx

或者实现IClonable接口: http : //msdn.microsoft.com/en-us/library/system.icloneable.aspx

我想出了一个很好的模式来处理这种情况。

 public class Base { public int BaseField; ///  /// Apply the state of the passed object to this object. ///  public virtual void ApplyState(Base obj) { BaseField = obj.BaseField; } } public class Derived : Base { public int DerivedField; public override void ApplyState(Base obj) { var src = srcObj as Derived; if (src != null) { DerivedField = src.DerivedField; } base.ApplyState(srcObj); } } 

给定任何两个共享类型为“Base”的对象,您可以将A应用于B或B到A.

我意识到其他几个答案可能触及了这个解决方案,但我想更完整地拼出来。

我找到的解决方案是填充基类,然后将该基类传递给派生类的构造函数。 派生类的构造函数根据基类填充其字段。

 class Base { private string name; public string Name { get; set; } private string address; public string Address { get; set; } } class Derived:Base { Derived(Base toCopy) { this.Name = toCopy.Name; this.Address = toCopy.Address; } private string field; public String field { get; set; } } namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Base b = new Base(); b.Address = "Iliff"; b.Name = "somename"; //You are now passing the base class into the constructor of the derived class. Derived d = new Derived(b); } } } 

我发现EMIT可能会帮助你。

因为我们将花费太长时间进行反思,但我们可以在Emit中快速进行。

  private static void CloneObjectWithIL(T source, T los) { var dynamicMethod = new DynamicMethod("Clone", null, new[] { typeof(T), typeof(T) }); ILGenerator generator = dynamicMethod.GetILGenerator(); foreach (var temp in typeof(T).GetProperties().Where(temp=>temp.CanRead&&temp.CanWrite)) { generator.Emit(OpCodes.Ldarg_1);// los generator.Emit(OpCodes.Ldarg_0);// s generator.Emit(OpCodes.Callvirt,temp.GetMethod); generator.Emit(OpCodes.Callvirt, temp.SetMethod); } generator.Emit(OpCodes.Ret); var clone = (Action) dynamicMethod.CreateDelegate(typeof(Action)); clone(source, los); } 

它可以用作此代码:

 public class Base { public string BaseField; } public class Derived : Base { public string DerivedField; } Base base = new Base(); //some alother code Derived derived = new Derived(); CloneObjectWithIL(base, derived); 

更快的代码是缓存它。

  // ReSharper disable once InconsistentNaming public static void CloneObjectWithIL(T source, T los) { //See http://lindexi.oschina.io/lindexi/post/C-%E4%BD%BF%E7%94%A8Emit%E6%B7%B1%E5%85%8B%E9%9A%86/ if (CachedIl.ContainsKey(typeof(T))) { ((Action) CachedIl[typeof(T)])(source, los); return; } var dynamicMethod = new DynamicMethod("Clone", null, new[] { typeof(T), typeof(T) }); ILGenerator generator = dynamicMethod.GetILGenerator(); foreach (var temp in typeof(T).GetProperties().Where(temp => temp.CanRead && temp.CanWrite)) { if (temp.GetAccessors(true)[0].IsStatic) { continue; } generator.Emit(OpCodes.Ldarg_1);// los generator.Emit(OpCodes.Ldarg_0);// s generator.Emit(OpCodes.Callvirt, temp.GetMethod); generator.Emit(OpCodes.Callvirt, temp.SetMethod); } generator.Emit(OpCodes.Ret); var clone = (Action) dynamicMethod.CreateDelegate(typeof(Action)); CachedIl[typeof(T)] = clone; clone(source, los); } private static Dictionary CachedIl { set; get; } = new Dictionary(); 

只是改变这个。

 Derived d = (Derived)b; 

此外,您的名称数据类型应为字符串,而不是int