C#数组copy与clone的一个问题?

大多数程序现在都用  泛型集合类型  而非数组来存储数据集合。


“shallow copy”=copy;“deep copy”=clone


值类型没有改变。不发生跟随改变。

using System;

namespace Array的copy和Clone
{
    class Program
    {
        static void Main(string[] args)
        {
            test01();
            Console.WriteLine("Hello World!");

            Console.ReadLine();
        }


        static void test01()
        {
            int[] a = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            int[] b =new int[10];
            Array.Copy(a, 3, b, 2, 5);
            int[] c = (int[])a.Clone();
            a[4] = 99;

            for (int i = 0; i < a.Length; i++)
            {
                Console.WriteLine(a[i]);
            }
            Console.WriteLine("______________------___________");
            for (int i = 0; i < b.Length; i++)
            {
                Console.WriteLine(b[i]);
            }
            Console.WriteLine("______________------___________");
            for (int i = 0; i < c.Length; i++)
            {
                Console.WriteLine(c[i]);
            }
        }
    }
}

输出:

0
1
2
3
99
5
6
7
8
9
______________------___________
0
0
3
4
5
6
7
0
0
0
______________------___________
0
1
2
3
4
5
6
7
8
9
Hello World!

Clone说是浅拷贝。 

 Clone说是浅拷贝

我的理解是不是说直接把引用拷贝过去了。应该随变(随之改变)的。考虑到int是值类型,存储在栈区上面,不存在引用一说。

Copy直接要求必须输入一个新的Array,所以这个好理解,肯定不会随变的。真是这样吗?


现在的问题就剩下一个了。需要引用类型的例子。

我们需要自建一个新的类型Class来重新实验,比如Array中存储的是Person,Person存储一个字段是string类型的名字。

看代码:增加一个新类Person,引用类型,存储在堆中。可引用。

using System;

namespace Array的copy和Clone
{
    class Program
    {
        static void Main(string[] args)
        {
            // test01();
            test02();



            Console.WriteLine("Hello World!");

            Console.ReadLine();
        }


        static void test01()
        {
            int[] a = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            int[] b =new int[10];
            Array.Copy(a, 3, b, 2, 5);
            int[] c = (int[])a.Clone();
            a[4] = 99;
            for (int i = 0; i < a.Length; i++)
            {
                Console.WriteLine(a[i]);
            }
            Console.WriteLine("______________Copy结果:___________");
            for (int i = 0; i < b.Length; i++)
            {
                Console.WriteLine(b[i]);
            }
            Console.WriteLine("______________Clone结果:___________");
            for (int i = 0; i < c.Length; i++)
            {
                Console.WriteLine(c[i]);
            }
        }

        static void test02()
        {
            Person[] p1 = new Person[]
            {
                new Person("Tom1"),
                new Person("Tom2"),
                new Person("Tom3"),
                new Person("Tom4"),
                new Person("Tom5"),
                new Person("Tom6"),
            };
            Person[] p2 = new Person[5];
            Array.Copy(p1, p2, 5);
            Person[] p3 = (Person[])p1.Clone();
            p1[3].name = "Jack00";
            for (int i = 0; i < p1.Length; i++)
            {
                Console.WriteLine(p1[i].name);
            }
            Console.WriteLine("______________------___________");
            for (int i = 0; i < p2.Length; i++)
            {
                Console.WriteLine(p2[i].name);
            }
            Console.WriteLine("______________------___________");
            for (int i = 0; i < p3.Length; i++)
            {
                Console.WriteLine(p3[i].name);
            }

        }

    }

    class Person
    {
        public string name;
        public Person(string name)
        {
            this.name = name;
        }
    }

}

输出:

Tom1
Tom2
Tom3
Jack00
Tom5
Tom6
______________Copy结果:___________
Tom1
Tom2
Tom3
Jack00
Tom5
______________Clone结果:___________
Tom1
Tom2
Tom3
Jack00
Tom5
Tom6
Hello World!

看结果知道:联动了,随之改变(随变)。

但是copyClone都随之改变而改变。

我们准备好了一切,并做了猜测,发现错了。

方法调用时如何?

using System;

namespace Array的copy和Clone
{
    class Program
    {
        static void Main(string[] args)
        {
            // test01();
            test02();



            Console.WriteLine("Hello World!");

            Console.ReadLine();
        }


        static void test01()
        {
            int[] a = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            int[] b =new int[10];
            Array.Copy(a, 3, b, 2, 5);
            int[] c = (int[])a.Clone();
            a[4] = 99;
            for (int i = 0; i < a.Length; i++)
            {
                Console.WriteLine(a[i]);
            }
            Console.WriteLine("______________------___________");
            for (int i = 0; i < b.Length; i++)
            {
                Console.WriteLine(b[i]);
            }
            Console.WriteLine("______________------___________");
            for (int i = 0; i < c.Length; i++)
            {
                Console.WriteLine(c[i]);
            }
        }

        static void test02()
        {
            Person[] p1 = new Person[]
            {
                new Person("Tom1"),
                new Person("Tom2"),
                new Person("Tom3"),
                new Person("Tom4"),
                new Person("Tom5"),
                new Person("Tom6"),
            };
            Person[] p2 = new Person[5];
            Array.Copy(p1, p2, 5);
            Person[] p3 = (Person[])p1.Clone();
            PrintArray1(p1);
            PrintArray2(p2);
            PrintArray3(p3);
            Console.WriteLine("------------------------华丽分割线----------------");
            for (int i = 0; i < p1.Length; i++)
            {
                if (i==3)
                {
                    p1[3].name = "Jack01";
                }
                Console.WriteLine(p1[i].name);
            }
            Console.WriteLine("______________Copy结果:___________");
            for (int i = 0; i < p2.Length; i++)
            {
                Console.WriteLine(p2[i].name);
            }
            Console.WriteLine("______________Clone结果:___________");
            for (int i = 0; i < p3.Length; i++)
            {
                Console.WriteLine(p3[i].name);
            }

        }
        static void PrintArray1(Person[] array)
        {
            for (int i = 0; i < array.Length; i++)
            {
                if (i == 3)
                {
                    array[3].name = "Jack00";
                }
                Console.WriteLine(array[i].name);
            }
        }
        static void PrintArray2(Person[] array)
        {
            for (int i = 0; i < array.Length; i++)
            {
                Console.WriteLine(array[i].name);
            }
        }
    }

    class Person
    {
        public string name;
        public Person(string name)
        {
            this.name = name;
        }
    }

}

 输出:

Tom1
Tom2
Tom3
Jack00
Tom5
Tom6
Tom1
Tom2
Tom3
Jack00
Tom5
Tom1
Tom2
Tom3
Jack00
Tom5
Tom6
------------------------华丽分割线----------------
Tom1
Tom2
Tom3
Jack01
Tom5
Tom6
______________Copy结果:___________
Tom1
Tom2
Tom3
Jack01
Tom5
______________Clone结果:___________
Tom1
Tom2
Tom3
Jack01
Tom5
Tom6
Hello World!

引用类型通过copy和Clone复制后都随变。 即使是发生了方法调用。


三者联动:

using System;

namespace Array的copy和Clone
{
    class Program
    {
        static void Main(string[] args)
        {
            // test01();
            test02();



            Console.WriteLine("Hello World!");

            Console.ReadLine();
        }


        static void test01()
        {
            int[] a = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            int[] b =new int[10];
            Array.Copy(a, 3, b, 2, 5);
            int[] c = (int[])a.Clone();
            a[4] = 99;
            for (int i = 0; i < a.Length; i++)
            {
                Console.WriteLine(a[i]);
            }
            Console.WriteLine("______________------___________");
            for (int i = 0; i < b.Length; i++)
            {
                Console.WriteLine(b[i]);
            }
            Console.WriteLine("______________------___________");
            for (int i = 0; i < c.Length; i++)
            {
                Console.WriteLine(c[i]);
            }
        }

        static void test02()
        {
            Person[] p1 = new Person[]
            {
                new Person("Tom1"),
                new Person("Tom2"),
                new Person("Tom3"),
                new Person("Tom4"),
                new Person("Tom5"),
                new Person("Tom6"),
            };
            Person[] p2 = new Person[5];
            Array.Copy(p1, p2, 5);
            Person[] p3 = (Person[])p1.Clone();
            Console.WriteLine("----P1:----");
            PrintArray1(p1);
            Console.WriteLine("----P2:----");
            PrintArray2(p2);
            Console.WriteLine("----P3:----");
            PrintArray3(p3);
            Console.WriteLine("------------------------华丽分割线----------------");
            for (int i = 0; i < p1.Length; i++)
            {
                if (i==3)
                {
                    p1[3].name = "Jack01";
                }
                Console.WriteLine(p1[i].name);
            }
            Console.WriteLine("______________Copy结果:___________");
            for (int i = 0; i < p2.Length; i++)
            {
                Console.WriteLine(p2[i].name);
            }
            Console.WriteLine("______________Clone结果:___________");
            for (int i = 0; i < p3.Length; i++)
            {
                Console.WriteLine(p3[i].name);
            }

        }
        static void PrintArray1(Person[] array)
        {
            for (int i = 0; i < array.Length; i++)
            {
                if (i == 3)
                {
                    array[3].name = "Jack00";
                }
                Console.WriteLine(array[i].name);
            }
        }
        static void PrintArray2(Person[] array)
        {
            for (int i = 0; i < array.Length; i++)
            {
                if (i == 1)
                {
                    array[1].name = "Jack02改变他";
                }
                Console.WriteLine(array[i].name);
            }
        }
        static void PrintArray3(Person[] array)
        {
            for (int i = 0; i < array.Length; i++)
            {
                if (i == 2)
                {
                    array[2].name = "Jack03改变他";
                }
                Console.WriteLine(array[i].name);
            }
        }
    }

    class Person
    {
        public string name;
        public Person(string name)
        {
            this.name = name;
        }
    }

}

输出:

----P1:----
Tom1
Tom2
Tom3
Jack00
Tom5
Tom6
----P2:----
Tom1
Jack02改变他
Tom3
Jack00
Tom5
----P3:----
Tom1
Jack02改变他
Jack03改变他
Jack00
Tom5
Tom6
------------------------华丽分割线----------------
Tom1
Jack02改变他
Jack03改变他
Jack01
Tom5
Tom6
______________Copy结果:___________
Tom1
Jack02改变他
Jack03改变他
Jack01
Tom5
______________Clone结果:___________
Tom1
Jack02改变他
Jack03改变他
Jack01
Tom5
Tom6
Hello World!

指向同一地址:仅仅只是引用的传递,引用名称(栈中变量名和栈中位置)虽然变了,但是栈中变量指向的堆中地址(栈中记录的Array所在的堆中地址)还是同一个。


结论:

请牢记:这俩(Copy和Clone)

  • 对值拷贝:不联动。
  • 对引用的拷贝,都是联动改变的。随变。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值