C# 从派生类复制基类的内容
我目前有一个派生类和一个基类。如何使派生类的基类等于我拥有的基类?浅显的复制品行得通吗C# 从派生类复制基类的内容,c#,C#,我目前有一个派生类和一个基类。如何使派生类的基类等于我拥有的基类?浅显的复制品行得通吗 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
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 ?
}
}
}
改变这个
Derived d = (Derived)b;
此外,您的名称数据类型应该是string,而不是int您必须手动将
基本
实例的字段复制到新的派生
实例
执行此操作的常见方法是提供副本构造函数:
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; }
这没有多大意义(其他属性也是如此)
公共字符串字段{get;set;}
表示编译器将自动创建一个私有字段。您的字段
字段将永远不会被使用
或者只写公共字符串字段{get;set;}
,因为私有字段将自动创建。或者声明字段
属性,以便使用您的私有字段:
private string field;
public string Field {
get {
return field;
}
set {
field = value;
}
}
如果我理解正确,这将起作用:
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);
您始终可以使用Object.MemberwiseClone来复制它 或实现IClonable接口:
为基类创建一个复制构造函数,在这样做时,您还需要创建一个无参数的构造函数,并且通过添加复制构造函数,编译器将不再生成默认构造函数。然后在派生类中调用基类的复制构造函数
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()
{ }
}
另一种方法是将基类映射到派生类:
/// <summary>
/// Maps the source object to target object.
/// </summary>
/// <typeparam name="T">Type of target object.</typeparam>
/// <typeparam name="TU">Type of source object.</typeparam>
/// <param name="target">Target object.</param>
/// <param name="source">Source object.</param>
/// <returns>Updated target object.</returns>
public static T Map<T, TU>(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.Where(x=>x.CanWrite == true).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;
}
我想出了一个很好的模式来处理这种情况
public class Base
{
public int BaseField;
/// <summary>
/// Apply the state of the passed object to this object.
/// </summary>
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);
}
}
公共类基
{
公共国际基地;
///
///将传递对象的状态应用于此对象。
///
公共虚拟空应用程序状态(基本对象)
{
BaseField=对象BaseField;
}
}
派生的公共类:基
{
公共领域;
公共覆盖无效ApplyState(基本对象)
{
var src=导出的srcObj;
如果(src!=null)
{
DerivedField=src.DerivedField;
}
基苹果酸盐(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);
}
}
}
我发现我可以帮你做这件事 因为我们花在反射上的时间太长了,但我们可以快速地发射
private static void CloneObjectWithIL<T>(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<T, T>) dynamicMethod.CreateDelegate(typeof(Action<T, T>));
clone(source, los);
}
缓存代码的速度越快
// ReSharper disable once InconsistentNaming
public static void CloneObjectWithIL<T>(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<T, T>) 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<T, T>) dynamicMethod.CreateDelegate(typeof(Action<T, T>));
CachedIl[typeof(T)] = clone;
clone(source, los);
}
private static Dictionary<Type, Delegate> CachedIl { set; get; } = new Dictionary<Type, Delegate>();
//ReSharper禁用一次不一致的命名
公共静态无效克隆对象(T源,T los)
{
//看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)))
{
(行动)CachedIl[类型(T)](来源,服务水平);
返回;
}
var dynamicMethod=newdynamicmethod(“克隆”,null,new[]{typeof(T),typeof(T)});
ILGenerator=dynamicMethod.GetILGenerator();
foreach(typeof(T).GetProperties()中的var temp,其中(temp=>temp.CanRead&&temp.CanWrite))
{
if(临时GetAccessors(true)[0].IsStatic)
{
继续;
}
generator.Emit(操作码.Ldarg_1);//服务水平
生成器.Emit(操作码.Ldarg_0);//s
生成器.Emit(操作码.Callvirt,temp.GetMethod);
生成器.Emit(操作码.Callvirt,温度设置方法);
}
生成器.Emit(操作码.Ret);
var clone=(Action)dynamicMethod.CreateDelegate(typeof(Action));
CachedIl[typeof(T)]=克隆;
克隆(来源,los);
}
私有静态字典CachedIl{set;get;}=new Dictionary();
根据mnyarar代码,有必要更新获取属性的方法:
public static T Map<T, TU>(this T target, TU source)
{
// list of writable properties of the destination
List<PropertyInfo> tprops = typeof(T).GetTypeInfo().DeclaredProperties
.Where(x => x.CanWrite == true).ToList();
tprops.ForEach(prop =>
{
// check whether source object has the the property
var sp = source.GetType().GetProperty(prop.Name);
if (sp != null)
{
// if yes, copy the value to the matching property
var value = sp.GetValue(source, null);
target.GetType().GetProperty(prop.Name).SetValue(target, value, null);
}
});
}
公共静态T映射(此T目标,TU源)
{
//目标的可写属性列表
List tprops=typeof(T).GetTypeInfo().DeclaredProperties
.Where(x=>x.CanWrite==true).ToList();
tprops.ForEach(prop=>
{
//检查源对象是否具有该属性
var sp=source.GetType().GetProperty(prop.Name);
如果(sp!=null)
{
//如果是,请将该值复制到匹配的属性
var value=sp.GetValue(源,空);
target.GetType().GetProperty(prop.Name).SetValue(target,value,null);
}
});
}
要引用同一对象还是复制?它可能引用同一对象为什么需要“b”和“d”?他们两个的目的是什么?我试图理解你的代码,但我发现自己有点困惑。如果您想与基类型对话,为什么不实例化“d”并将其存储为“b”呢?我建议您声明d,然后通过casting从d设置b,这是行不通的。您至少需要强制转换它,然后您仍然会遇到麻烦,Base
不能分配给派生的
;Base
不是Derived
的类型,相反。您不能从Base强制转换为派生类型。它提供空引用例外情况在这种情况下如何使用MemberwiseClone
?它将生成基类,而不是派生类。如果基类中有100多个属性,而派生类中只有一个属性,该怎么办?必须有更好的方法来自动匹配和赋值,毕竟基是同一个类。@Samir找到方法了吗?@Samir我认为反射是唯一的选择,我喜欢这个解决方案-但是代码中有两个错误:1)GetProperte
// ReSharper disable once InconsistentNaming
public static void CloneObjectWithIL<T>(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<T, T>) 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<T, T>) dynamicMethod.CreateDelegate(typeof(Action<T, T>));
CachedIl[typeof(T)] = clone;
clone(source, los);
}
private static Dictionary<Type, Delegate> CachedIl { set; get; } = new Dictionary<Type, Delegate>();
public static T Map<T, TU>(this T target, TU source)
{
// list of writable properties of the destination
List<PropertyInfo> tprops = typeof(T).GetTypeInfo().DeclaredProperties
.Where(x => x.CanWrite == true).ToList();
tprops.ForEach(prop =>
{
// check whether source object has the the property
var sp = source.GetType().GetProperty(prop.Name);
if (sp != null)
{
// if yes, copy the value to the matching property
var value = sp.GetValue(source, null);
target.GetType().GetProperty(prop.Name).SetValue(target, value, null);
}
});
}