【问题标题】:Cloning a C# Reference Type to a Derived Reference Type将 C# 引用类型克隆为派生引用类型
【发布时间】:2010-11-23 00:13:24
【问题描述】:

来自 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();

我想创建一个“Derived”实例,同时对 Base 对象进行成员复制 - 最好不要手动分配它们。

注意:也许这更适合值类型?

【问题讨论】:

  • 对我来说听起来很奇怪。愿意提供更多背景信息吗?

标签: c# clone reference-type


【解决方案1】:

由于您无法更改对象的类型,因此您有几个选择:

  • 封装 Base
  • 使用从Base复制值的构造函数
  • 通过反射或类似方法从Base 复制属性

对于后者,MiscUtil 有一个有用的工具:

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...
}

或 (cmets) 让基地复制自己:

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 的字段)

【讨论】:

  • 您可以通过使用复制构造函数来改进“手动复制”版本 - 这样您可以要求 Base 创建自己的副本,如果需要,它也可以使用它的私有内容 -如果它有多个派生类,它也可以工作。
【解决方案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());
}

【讨论】:

    猜你喜欢
    • 2014-01-09
    • 1970-01-01
    • 1970-01-01
    • 2019-12-20
    • 1970-01-01
    • 2018-03-26
    • 2012-02-12
    • 2020-06-01
    相关资源
    最近更新 更多