从派生类复制基类的内容
我目前有一个派生类和一个基类。 如何使派生类的基类等于我拥有的基类? 浅拷贝会起作用吗?
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