MemberWiseClone如何使用克隆属性创建新对象?

Pro*_*ofK 4 c# reflection clone dynamic

我想创建一个更受约束的版本MemberwiseClone,但意识到我自己的C#代码可以添加属性的唯一方法是使用dynamic,但是这不能给对象提供与原始类型相同的类型.另一个更丑陋的选择是为新克隆发出源代码并在运行时编译它,但这会带来复杂性.装配参考等,我不关心保持简单.

现在我只是使用MemberwiseClone,但我真的好奇它是如何工作的.我找不到任何反编译的来源.

Iva*_*oev 12

它基本上在MemberwiseCloneMSDN 文档中解释:

MemberwiseClone方法通过创建新对象,然后将当前对象的非静态字段复制到新对象来创建浅表副本.如果字段是值类型,则执行字段的逐位复制.如果字段是引用类型,则复制引用但不引用引用的对象; 因此,原始对象及其克隆引用相同的对象.

上述的实际实现由CLR在内部实现.您可以将其视为以下标准C#代码的优化变体:

using System.Reflection;
using System.Runtime.Serialization;

public static object CustomMemberwiseClone(object source)
{
    var clone = FormatterServices.GetUninitializedObject(source.GetType());
    for (var type = source.GetType(); type != null; type = type.BaseType)
    {
        var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
        foreach (var field in fields)
            field.SetValue(clone, field.GetValue(source));
    }
    return clone;
}
Run Code Online (Sandbox Code Playgroud)

即获取实际类型,在不调用任何构造函数的情况下创建该类型的新实例,并从源对象复制每个实例字段值.

同样,实际的内部实现是不同的(如注释中所指出的),上面的片段只是为了演示原理以及如何通过反射实现具有相同语义的方法(当然这将比CLR方法慢得多) ).

OP增加:请参阅Ivan的评论,以获得我正在寻求的进一步解释.我认为这些部分是他的答案,并会基于他们接受.

  • 内部对GC Refs(指针)有一些特别的关注,但同样没有什么不同,例如在里面用`string`复制`struct`.无论如何,现在我看到我的答案没有解决你的问题,所以我要删除它. (2认同)
  • 不,@ Ivan,不要删除它,你对它的评论解释得很好,我认为评论部分是答案. (2认同)