MemberWiseClone如何使用克隆属性创建新对象?
我想创建一个更受限制的MemberwiseClone
版本,但是我意识到我自己的C#代码可以为对象添加属性的唯一方法是使用dynamic
,但这不能给对象提供与原始对象相同的类型。 另一个更丑陋的选择是为新克隆发出源代码并在运行时编译它,但这会带来复杂性。 assembly参考等,我不关心保持简单。
现在我只是使用MemberwiseClone
,但我真的很好奇它是如何工作的。 我找不到任何反编译的来源。
它基本上在MemberwiseClone
MSDN 文档中解释:
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; }
即获取实际类型,在不调用任何构造函数的情况下创建该类型的新实例,并从源对象复制每个实例字段值。
同样,实际的内部实现是不同的(如注释中所指出的),上面的片段只是为了演示原理以及如何通过reflection实现具有相同语义的方法(当然这将比CLR方法慢得多) )。
OP增加:请参阅Ivan的评论,以获得我正在寻求的进一步解释。 我认为这些部分是他的答案,并会基于他们接受。
- 为什么后续的直接方法调用比第一次调用要快得多?
- 保持应用程序数据库不可知(ADO.NET与封装DB逻辑)
- 如何让DataContractJsonSerializer将对象序列化为字符串?
- 使用entity framework的SQL查询运行速度较慢,使用错误的查询计划
- System.Data.OleDb.OleDbConnectionInternal..ctor:未指定的错误
- 由于CommandName =“edit”,GridView OnRowUpdating不会触发
- 在MigraDoc中将页码对齐到右角
- Mono PrivateFontCollection.AddFontFile错误的解决方法
- 如何获取访问ASP.NET应用程序的当前用户?