现在的位置: 首页 > 综合 > 正文

c# 浅层复制与深层复制

2012年09月10日 ⁄ 综合 ⁄ 共 3041字 ⁄ 字号 评论关闭

最近碰到了一个比较复杂的类的复制问题。

.net中对于所有的类都有一个继承object得来的MemberwiseClone方法。MemberwiseClone方法提供了类的浅复制。为什么说是浅复制呢?使用MemberwiseClone方法进行复制时,对于类中的值类型会创建新的变量,而对于引用变量来说,会指向原来的引用并不创建新的引用变量,详细介绍可参见以下链接。

http://msdn.microsoft.com/zh-cn/library/system.object.memberwiseclone.aspx

msdn上给出了一个简单包含引用类型的类实现深层复制的方法,但是如果类中含有list属性的话,list本身是引用类型,“=”符号不会产生该list的副本只是复制了引用,所以需要用迭代来复制整个list。用代码对深层复制大概进行一下总结:

    class Program
    {
        static void Main(string[] args)
        {
            School school1 = new School();
            //调用School的Clone方法创建深层副本
            School school2 = (School)school1.Clone();

            //修改school1的属性,看是否会对school2造成影响
            school1.President.Name = "刘某";
            school1.Grades[0].ID = 3;
            school1.Buildings[0] = "3楼";

            Console.ReadLine();
        }
    }

public class School : ICloneable
{
    public string City { get; set; }
    public string Name { get; set; }
    public President President { get; set; }
    public List<Grade> Grades { get; set; }
    public List<string> Buildings { get; set; }

    /// <summary>
    /// Initialize School
    /// </summary>
    public School()
    {
        City = "A市";
        Name = "A市一中";

        President = new President
        {
            Age=50,
            Name ="张某"
        };

        Grades = new List<Grade>();
        Grades.Add(new Grade{ID=1, Name="一年级"});
        Grades.Add(new Grade{ID=2, Name="二年级"});

        Buildings = new List<string>();
        Buildings.Add("1楼");
        Buildings.Add("2楼");
    }

    /// <summary>
    /// Deep Copy School
    /// </summary>
    /// <returns>Deep Copy</returns>
    public object Clone()
    {
        //浅复制一个副本
        School newschool = (School)this.MemberwiseClone();

        //调用President的Clone方法,为President创建一个新的对象
        newschool.President = (President)this.President.Clone();

        //清空两个list
        newschool.Grades = new List<Grade>();
        newschool.Buildings = new List<string>();

        //将Grades添加到新的school里
        foreach (var grade in Grades)
        {
            newschool.Grades.Add((Grade)grade.Clone());//通过调用Grade的Clone方法进行复制
        }

        //将Buildings添加到新的school里
        foreach (var building in Buildings)
        {
            newschool.Buildings.Add(building);
            //string类型虽然是引用类型,但是在.net框架里面,“=”符号是创建一个新的string对象存在堆里,所以不用clone方法也可以实现string的复制
            //newschool.Buildings.Add((string)building.Clone());
        }

        return newschool;
    }
}

public class Grade : ICloneable
{
    public int ID { get; set; }
    public string Name { get; set; }

    public object Clone()
    {
        return this.MemberwiseClone();
    }
}

public class President : ICloneable
{
    public int Age { get; set; }
    public string Name { get; set; }

    public object Clone()
    {
        return this.MemberwiseClone();
    }
}

public class Person : IComparable
{
    public string FirstName;
    public string LastName;

    public Person()
    { }

    public Person(string first, string last)
    {
        FirstName = first;
        LastName = last;
    }

    public int CompareTo(object obj)
    {
        Person other = obj as Person;
        int result = this.LastName.CompareTo(other.LastName);
        this.MemberwiseClone();
        return result;
    }
}

 

以上是深层复制大概的使用方法,用这种方法实现以后发现网上有牛人有更简单的方法,不用实现ICloneable接口的Clone方法,使用序列化解决了这个问题。大家可以参考一下下面这个资料。

http://www.cnblogs.com/zhangji/archive/2011/02/23/1961897.html

抱歉!评论已关闭.