我想创建一个更受限制的MemberwiseClone
版本,但我意识到我自己的C#代码可以为对象添加属性的唯一方法是使用dynamic
,但这不能给出对象与原始对象的类型相同。另一个更丑陋的选择是为新克隆发出源代码并在运行时编译它,但这会带来复杂性。装配参考等,我不在乎保持简单。
现在我只使用MemberwiseClone
,但我对它是如何工作非常好奇。我无法找到任何已反编译的来源。
答案 0 :(得分:12)
基本上在MemberwiseClone
MSDN documentation中解释了:
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;
}
即。获取实际类型,创建该类型的新实例,而不调用任何构造函数并从源对象复制每个实例字段值。
同样,实际的内部实现是不同的(如注释中所指出的),上面的代码片段只是为了演示原理以及如何通过反射实现具有相同语义的方法(当然这将比CLR方法)。
OP增加:请参阅下面的Ivan评论,了解我正在寻求的进一步解释。我认为这些部分是他的答案,并会基于他们接受。