c#深度复制 浅度复制

以下内容为转载,分享给大家。
原创地址

c#中没有指针的概念。但并不代表c#中没有引用的地址。相反,可能很多人会忽略这点。如果不遇到问题,我可能会一直在这个地方模模糊糊吧。
举个实际碰到的例子。
有一个类。实例化复制后想保留这个实例的一个备份。
例如
//Clone类中包含一个int length字段。
Clone cloneTest=new Clone();
Clone cloneCopy=new Clone();
cloneTest…length=0;
cloneCopy=cloneTest;
到这个部分都是正常的,实际上cloneTest和cloneCopy中的length值都变为0了。 但如果接着加一行代码
cloneTest.length=1;
预期是希望cloneTest中length=1而cloneCopy中length=0;但实际两者都变为1了。
指针没学好。没想到c#没指针但是却包含了指针的作用。
这里出现这个原因就是因为类是个引用类型,所以当执行
cloneCopy=cloneTest;时,是将地址给过去了。于是当然一者变。两者都会变了。
c#中的引用类型采用这种方法都是给地址。复制引用地址就是浅度复制。而复制对象的值,创建新的对象就是深度复制。
于是现在的问题就要记住哪些为引用类型,哪些为值类型了。
以下不全,只记录了我用到过的。
引用类型:
字符串:string型 最常见的引用类型,他被定义成引用类型的意义我不知道。但这里要强调的是,它被重写了Equal方法。使用方法与值类型类似。(实际上给string赋新值是重新给赋了一个新的地址)所以在大部分情况下就把他当成值类型没啥问题。

数组

接口
值类型:
结构体
数值类型
枚举类型
bool类型
这样,深度复制和浅度复制的意义就产生了。我想备份一个实例化后的类的数据。结果它会跟着变化,这是很郁闷的事情。这种情况就要进行深度复制。
深度复制方法很多。这是我在网上找的一个方法,特别简单。原理也很清晰。
为了实现深度复制,我们就必须遍历有相互引用的对象构成的图,并需要处理其中的循环引用结构。这无疑是十分复杂的。幸好借助.Net的序列化和反序列化机制,可以十分简单的深度Clone一个对象。原理很简单,首先将对象序列化到内存流中,此时对象和对象引用的所用对象的状态都被保存到内存中。.Net的序列化机制会自动处理循环引用的情况。然后将内存流中的状态信息反序列化到一个新的对象中。这样一个对象的深度复制就完成了。

深度复制帮助类,验证过,这个类是可用的。使用的时候只需建个内部类即可

public static class ObjectCopier
{
    /// 
    /// Perform a deep Copy of the object.
    /// 
    /// The type of object being copied.
    /// The object instance to copy.
    /// The copied object.
    public static T Clone<T>(T source)
    {
        if (!typeof(T).IsSerializable)
        {
            throw new ArgumentException("The type must be serializable.", "source");
        }

        //Don't serialize a null object, simply return the default for that object
        if (Object.ReferenceEquals(source, null))
        {
            return default(T);
        }

        IFormatter formatter = new BinaryFormatter();
        Stream stream = new MemoryStream();
        using (stream)
        {
            formatter.Serialize(stream, source);
            stream.Seek(0, SeekOrigin.Begin);
            return (T)formatter.Deserialize(stream);
        }
    }
}  

你可能感兴趣的:(c#)