NET的深复制方法(以C#语言为例)_第1页
NET的深复制方法(以C#语言为例)_第2页
NET的深复制方法(以C#语言为例)_第3页
NET的深复制方法(以C#语言为例)_第4页
NET的深复制方法(以C#语言为例)_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、NET的深复制方法(以C#语言为例)深复制需要将对象实例中字段引用的对象也进行复制,在平时的编程工作中经常要用到这种复制方式,下面以c#为例来演示一下方法。很多时候我们复制一个对象实例A到实例B,在用实例B去做其他事情的时候,会对实例B进行修改,为保证对B的修改不会影响到A的正常使用,就需要使用到深复制。 我在网上搜到一些深复制的方法,同时写了几组例子对这些方法进行测试。 我的操作系统版本为Win7旗舰版,.NET Framework版本是4.5 测试程序 我建了一个C#窗体应用程序(Winform),其主窗口FormMain的Load函数内容如下:private void FormMain_

2、Load(object sender, EventArgs e) /测试1:深度复制 自定义类 try Console.WriteLine(= 深度复制 自定义类 =); TestClass test1 = new TestClass(); test1.a = 10; test1.b = hello world!; test1.c = new string x, y, z ; TestClass test2 = new TestClass(); test2.a = 11; test2.b = hello world2!; test2.c = new string i, j, k ; test1

3、.d = test2; Console.WriteLine(-test1_start-); Console.WriteLine(test1); Console.WriteLine(-test1_end-); TestClass test3 = (TestClass)DataManHelper.DeepCopyObject(test1); Console.WriteLine(-test3_start-); Console.WriteLine(test3); Console.WriteLine(-test3_end-); catch (Exception ex) Console.WriteLine

4、(ex.ToString(); /测试2:深度复制 可序列化的自定义类try Console.WriteLine(= 深度复制 可序列化的自定义类 =); TestClassWithS test1 = new TestClassWithS(); test1.a = 10; test1.b = hello world!; test1.c = new string x, y, z ; TestClassWithS test2 = new TestClassWithS(); test2.a = 11; test2.b = hello world2!; test2.c = new string i,

5、j, k ; test1.d = test2; Console.WriteLine(-test1_start-); Console.WriteLine(test1); Console.WriteLine(-test1_end-); TestClassWithS test3 = (TestClassWithS)DataManHelper.DeepCopyObject(test1); Console.WriteLine(-test3_start-); Console.WriteLine(test3); Console.WriteLine(-test3_end-);catch (Exception

6、ex) Console.WriteLine(ex.ToString(); /测试3:深度复制 DataTabletry Console.WriteLine(= 深度复制 DataTable =); DataTable dtKirov = new DataTable(TestTable); dtKirov.Columns.Add(Col1); dtKirov.Columns.Add(Col2); dtKirov.Columns.Add(Col3); dtKirov.Rows.Add(1-1, 1-2, 1-3); dtKirov.Rows.Add(2-1, 2-2, 2-3); dtKirov.

7、Rows.Add(3-1, 3-2, 3-3); Console.WriteLine(= 复制前 =); for (int i = 0; i dtKirov.Columns.Count; i+) Console.Write(dtKirov.Columnsi.ColumnName + t); Console.WriteLine(n-); for (int i = 0; i dtKirov.Columns.Count; i+) for (int j = 0; j dtKirov.Rows.Count; j+) Console.Write(dtKirov.Rowsij.ToString() + t)

8、; Console.WriteLine(); Console.WriteLine(); DataTable dtDreadNought = (DataTable)DataManHelper.DeepCopyObject(dtKirov); Console.WriteLine(= 复制后 =); for (int i = 0; i dtDreadNought.Columns.Count; i+) Console.Write(dtDreadNought.Columnsi.ColumnName + t); Console.WriteLine(n-); for (int i = 0; i dtDrea

9、dNought.Columns.Count; i+) for (int j = 0; j System.ArgumentOutOfRangeException: 指定的参数已超出有效值的范围。 参数名: value 在 System.Windows.Forms.DataGridView.set_FirstDisplayedScrollingColumnIndex(Int32 value) - 内部异常堆栈跟踪的结尾 - 在 System.RuntimeMethodHandle.InvokeMethod(Object target, Object arguments, Signature sig

10、, Boolean constructor) 在 System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object parameters, Object arguments) 在 System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture) 在 System.Reflection.RuntimePrope

11、rtyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object index, CultureInfo culture) 在 System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object index) 在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 位置 d:MyProgramsDataCopyTestDataCopyTe

12、stDataManHelper.cs:行号 29 在 DataCopyTest.FormMain.FormMain_Load(Object sender, EventArgs e) 位置 d:MyProgramsDataCopyTestDataCopyTestFormMain.cs:行号 141 结论:使用这种方法进行所谓深复制,完全是自寻死路! 测试深复制方法3public static object DeepCopyObject(object obj) if (obj != null) object result = Activator.CreateInstance(obj.GetType

13、(); foreach (FieldInfo field in obj.GetType().GetFields() if (field.FieldType.GetInterface(IList, false) = null) field.SetValue(result, field.GetValue(obj); else IList listObject = (IList)field.GetValue(result); if (listObject != null) foreach (object item in (IList)field.GetValue(obj) listObject.Ad

14、d(DeepCopyObject(item); return result; else return null; 五个场景的测试结果为: I、可正常复制() II、可正常复制() III、未触发异常, 复制后DataTable无行列 IV、未触发异常,Text字段未赋值 V、未触发异常 结论:这个方法只适用于深复制具备简单结构的类(如类中只有基础字段、数组等),对于不支持序列化的对象也可以进行深复制。 测试深复制方法4 这段代码来源同方法3public static object DeepCopyObject(object obj) if (obj = null) return null; T

15、ype type = obj.GetType(); if (type.IsValueType | type = typeof(string) return obj; else if (type.IsArray) Type elementType = Type.GetType( type.FullName.Replace(, string.Empty); var array = obj as Array; Array copied = Array.CreateInstance(elementType, array.Length); for (int i = 0; i array.Length;

16、i+) copied.SetValue(DeepCopyObject(array.GetValue(i), i); return Convert.ChangeType(copied, obj.GetType(); else if (type.IsClass) object toret = Activator.CreateInstance(obj.GetType(); FieldInfo fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (F

17、ieldInfo field in fields) object fieldValue = field.GetValue(obj); if (fieldValue = null) continue; field.SetValue(toret, DeepCopyObject(fieldValue); return toret; else throw new ArgumentException(Unknown type); 五个场景的测试结果为: I、可正常复制() II、可正常复制() III、触发异常MissingMethodException “System.MissingMethodExc

18、eption”类型的第一次机会异常在 mscorlib.dll 中发生 System.MissingMethodException: 没有为该对象定义无参数的构造函数。 在 System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) 在 System.RuntimeType.CreateInsta

19、nceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) 在 System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) 在 System.Activator.CreateInstance(Type type, Boolean nonPublic) 在 S

20、ystem.Activator.CreateInstance(Type type) 在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 位置 d:MyProgramsDataCopyTestDataCopyTestDataManHelper.cs:行号 45 在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 位置 d:MyProgramsDataCopyTestDataCopyTestDataManHelper.cs:行号 53 在 DataCopyTest.FormMai

21、n.FormMain_Load(Object sender, EventArgs e) 位置 d:MyProgramsDataCopyTestDataCopyTestFormMain.cs:行号 99 IV、未触发异常,但Text字段也未赋值成功 V、触发异常MissingMethodException “System.MissingMethodException”类型的第一次机会异常在 mscorlib.dll 中发生 System.MissingMethodException: 没有为该对象定义无参数的构造函数。 在 System.RuntimeTypeHandle.CreateInsta

22、nce(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) 在 System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) 在 System.RuntimeType.Creat

23、eInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) 在 System.Activator.CreateInstance(Type type, Boolean nonPublic) 在 System.Activator.CreateInstance(Type type) 在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 位置 d:MyProgramsDataCopyTe

24、stDataCopyTestDataManHelper.cs:行号 45 在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 位置 d:MyProgramsDataCopyTestDataCopyTestDataManHelper.cs:行号 53 在 DataCopyTest.FormMain.FormMain_Load(Object sender, EventArgs e) 位置 d:MyProgramsDataCopyTestDataCopyTestFormMain.cs:行号 141 结论:这个方法的作用类似方法3,只能深复制

25、基本数据类型组成的类 具体问题具体分析 从上面的例子可以看出,想找一个放之四海而皆准的方式去深复制所有对象是很困难的。一些使用高级语言特性(反射)的深复制方法,即使可以在部分类上试用成功,也无法对所有的类都具备十足的把握。因此我认为应该采取下面的方式处理对象的深复制问题: 1、对于由基本数据类型组成的类,为之打上Serializable标签,直接使用序列化与反序列化的方法进行深复制 2、其他较为复杂的类型如DataGridView,可根据自身情况写一个方法进行深复制,之所以在这里说要根据自身情况写方法,是因为在对很多类进行复制时,你只需要复制对你有用的属性就行了。如TextBox控件中,只有T

26、ext一个属性对你是有用的,如果你需要在复制后的对象中用到Readonly等属性的值,那么在你自己实现的复制方法中,也加上对这些属性的赋值即可。这样做还有一个好处,就是方便进行一些定制化的开发。 如下面这段代码,就是对DataGridView的一个近似的深复制,这段代码将一个DataGridView(dgv)的内容复制到另一个DataGridView(dgvTmp)中,然后将dgvTmp传递给相关函数用于将DataGridView中的内容输出到Excel文档:DataGridView dgvTmp = new DataGridView();dgvTmp.AllowUserToAddRows = false; /不允许用户生成行,否则导出后会多出最后一行for (int i = 0; i dgv.Columns.Count; i+) dgvTmp.Columns.Add(dgv.Columnsi.Name, dgv.Columnsi.HeaderText); if (dgv.Columnsi.Defa

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论