Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 浅拷贝还是深拷贝?_C#_Deep Copy_Shallow Copy - Fatal编程技术网

C# 浅拷贝还是深拷贝?

C# 浅拷贝还是深拷贝?,c#,deep-copy,shallow-copy,C#,Deep Copy,Shallow Copy,我对这两种将一个对象复制到另一个对象的方法有点陌生。我感到困惑,无法找出深层复制和浅层复制之间的主要区别。。关于这一点,我已经讲了很多理论,但我需要用适当的例子来解释。。 我有一个将一个对象复制到另一个对象的程序。--> 这是浅拷贝还是深拷贝?任何人都可以提供一个合理的答案。如果是深度复制,那么请提供此程序的浅层复制代码,以执行与对象复制相同的工作,反之亦然 如果上面是浅拷贝,那么即使这也是浅拷贝--> 从链接 浅拷贝尽可能少地复制。一本浅薄的书 集合是集合结构的副本,而不是元素的副本。 使用浅

我对这两种将一个对象复制到另一个对象的方法有点陌生。我感到困惑,无法找出深层复制和浅层复制之间的主要区别。。关于这一点,我已经讲了很多理论,但我需要用适当的例子来解释。。 我有一个将一个对象复制到另一个对象的程序。-->

这是浅拷贝还是深拷贝?任何人都可以提供一个合理的答案。如果是深度复制,那么请提供此程序的浅层复制代码,以执行与对象复制相同的工作,反之亦然

如果上面是浅拷贝,那么即使这也是浅拷贝-->

从链接

浅拷贝尽可能少地复制。一本浅薄的书 集合是集合结构的副本,而不是元素的副本。 使用浅拷贝,两个集合现在共享单个 元素

深度复制复制一切。收藏的深度副本是两个 包含原始集合中所有元素的集合 重复的

您的示例是创建浅层副本

A ob1 = new A();
ob1.a = 10;
A ob2 = new A();
ob2 = ob1;

ob1.a = 5; // <-- If you see value of ob2.a after this line, it will be 5.
A ob1=新的A();
ob1.a=10;
A ob2=新的A();
ob2=ob1;

ob1.a=5;// 这是一个浅拷贝,因为如果您修改ob2的变量,然后尝试打印ob1,它们将是相同的。这是因为C#中的类会在它们之间创建链接。如果要进行深度复制,应该实现复制方法并手动复制字段。比如:

  class A
    {
        public int a = 0;
        public void display()
        {
            Console.WriteLine("The value of a is " + a);
        }

       public A Copy()
    {
        A a = new A();
        a.a = = this.a;
        return a;
    }



    }

在将第一个对象指定给第二个对象后,再编写几行代码来更改第一个对象的属性。然后对这两个对象调用display方法,并查看结果。这将向您揭示它实际上是一个浅拷贝。

在我看来,它不是严格的浅拷贝或深拷贝。如果我必须定义它,我会说浅拷贝

A ob1 = new A();
ob1.a = 10;
A ob2 = new A();
ob2 = ob1;

ob1.a = 5; // <-- If you see value of ob2.a after this line, it will be 5.
ob2=ob1; 这段代码创建两个对象引用,它们都引用同一个对象。因此,通过ob1对对象所做的任何更改都将反映在ob2的后续使用中

来自MSDN的示例最好解释浅拷贝、深拷贝和简单类拷贝的区别

 using System;

    public class IdInfo
    {
        public int IdNumber;

        public IdInfo(int IdNumber)
        {
            this.IdNumber = IdNumber;
        }
    }

    public class Person
    {
        public int Age;
        public string Name;
        public IdInfo IdInfo;

        public Person ShallowCopy()
        {
            return (Person)this.MemberwiseClone();
        }

        public Person DeepCopy()
        {
            Person other = (Person)this.MemberwiseClone();
            other.IdInfo = new IdInfo(this.IdInfo.IdNumber);
            other.Name = String.Copy(this.Name);
            return other;
        }
    }

    public class Example
    {
        public static void Main()
        {
            // Create an instance of Person and assign values to its fields.
            Person p1 = new Person();
            p1.Age = 42;
            p1.Name = "Sam";
            p1.IdInfo = new IdInfo(6565);

            // Perform a shallow copy of p1 and assign it to p2.
            Person p2 = (Person)p1.ShallowCopy();

            // Display values of p1, p2
            Console.WriteLine("Original values of p1 and p2:");
            Console.WriteLine("   p1 instance values: ");
            DisplayValues(p1);
            Console.WriteLine("   p2 instance values:");
            DisplayValues(p2);

            // Change the value of p1 properties and display the values of p1 and p2.
            p1.Age = 32;
            p1.Name = "Frank";
            p1.IdInfo.IdNumber = 7878;
            Console.WriteLine("\nValues of p1 and p2 after changes to p1:");
            Console.WriteLine("   p1 instance values: ");
            DisplayValues(p1);
            Console.WriteLine("   p2 instance values:");
            DisplayValues(p2);

            // Make a deep copy of p1 and assign it to p3.
            Person p3 = p1.DeepCopy();
            // Change the members of the p1 class to new values to show the deep copy.
            p1.Name = "George";
            p1.Age = 39;
            p1.IdInfo.IdNumber = 8641;
            Console.WriteLine("\nValues of p1 and p3 after changes to p1:");
            Console.WriteLine("   p1 instance values: ");
            DisplayValues(p1);
            Console.WriteLine("   p3 instance values:");
            DisplayValues(p3);

            // Make an equal of p1 and assign it to p4.
            Person p4 = new Person();
            p4 = p1;
            // Change the members of the p1 class to new values to show the equal copy.
            p1.Name = "Will";
            p1.Age = 30;
            p1.IdInfo.IdNumber = 8484;
            Console.WriteLine("\nValues of p1 and p4 after changes to p1:");
            Console.WriteLine("   p1 instance values: ");
            DisplayValues(p1);
            Console.WriteLine("   p4 instance values:");
            DisplayValues(p4);
        }

        public static void DisplayValues(Person p)
        {
            Console.WriteLine("      Name: {0:s}, Age: {1:d}", p.Name, p.Age);
            Console.WriteLine("      Value: {0:d}", p.IdInfo.IdNumber);
        }
    }
结果如下:

Original values of p1 and p2:    p1 instance values:
      Name: Sam, Age: 42
      Value: 6565    p2 instance values:
      Name: Sam, Age: 42
      Value: 6565

Values of p1 and p2 after changes to p1:    p1 instance values:
      Name: Frank, Age: 32
      Value: 7878    p2 instance values:
      Name: Sam, Age: 42
      Value: 7878

Values of p1 and p3 after changes to p1:    p1 instance values:
      Name: George, Age: 39
      Value: 8641    p3 instance values:
      Name: Frank, Age: 32
      Value: 7878

Values of p1 and p4 after changes to p1:    p1 instance values:
      Name: Will, Age: 30
      Value: 8484    p4 instance values:
      Name: Will, Age: 30
      Value: 8484

这既不是浅拷贝也不是深拷贝,这是引用拷贝。让我解释一下:变量有两种类型:值类型和引用类型

值类型是计算机内存中保存变量实际值的(命名)位置。例如:int是一种值类型,因此在编写这行代码时:

int MyInt = 5;
当执行这行代码时,运行时将在RAM中找到一个位置,并在其中写入值5。因此,如果您搜索该位置,您将发现实际值为5

相反,引用类型是内存中的一个(命名)位置,它实际上并不保存变量的值,而是保存该值所在的内存位置。例如,假设您编写了以下代码:

MyClass myObject = new MyClass();
发生的情况是虚拟机(运行时): 1-查找内存中的可用位置,创建MyClass的实例。假设该对象的位置恰好位于RAM中的字节#AA3D2

2-在内存中查找一个位置并创建MyClass类型的引用(引用是指向内存中某个位置的“箭头”),将其命名为“myObject”,并在其中存储值AA3D2

现在,如果您查看“myObject”变量,您将发现的不是类实例,而是表示保存该类实例的内存位置的AA3D2

现在,让我们检查一下给定OP的代码:

A ob1 = new A();
这将生成一个名为ob1的变量,创建一个类的实例,并将该类的位置存储在ob1中

ob1.a = 10;
ob1.display();
这将更改类中的变量a。然后调用display()方法

在这里,它创建一个名为ob2的变量,创建一个类a的实例,并将其位置分配给ob2

到目前为止,内存中有2个类实例A和2个变量,每个变量指向其中一个。 下面是有趣的部分: ob2=ob1

变量ob2被分配变量ob1的值。因为ob1包含A的第一个实例的内存位置,所以现在ob1和ob2都指向内存中的相同位置。用其中一个做任何事情都是用另一个做同样的事情


ob2=ob1表示您正在复制引用。

我赞同@docesam的答案和@Will Yu的部分答案


这既不是浅薄的副本,也不是深刻的副本,这是参考副本。-多塞萨姆


ob2=ob1;这段代码创建两个对象引用,它们都引用同一个对象。因此,通过ob1对对象所做的任何更改都将反映在ob2的后续使用中--余晖


根据:

数组的浅层副本仅复制数组的元素,无论它们是引用类型还是值类型,但它不复制引用引用的对象。新数组中的引用指向的对象与原始数组中的引用指向的对象相同

这里我们要注意两件事:

  • 浅拷贝复制元素
  • 浅层副本保留图元的原始参照
  • 接下来,让我分别解释这两个


    首先,我们使用
    名称
    属性创建一个
    Person
    类:

    class Person
    {
        public string Name {get; set;}
    }
    
    然后在
    Main()
    方法中,我们创建一个
    Person
    数组

    // Create 2 Persons.
    var person1 = new Person(){ Name = "Jack" };
    var person2 = new Person(){ Name = "Amy" };
    
    // Create a Person array.
    var arrPerson = new Person[] { person1, person2 };
    

    1。浅拷贝复制元素。

    如果替换浅拷贝中的第一个元素,则原始数组不应受到影响:

    // Create a shallow copy.
    var arrPersonClone = (Person[]) arrPerson.Clone();
    
    // Replace an element in the shallow copy.
    arrPersonClone[0] = new Person(){Name = "Peter"};
    
    // Display the contents of all arrays.
    Console.WriteLine( "After replacing the first element in the Shallow Copy" );
    Console.WriteLine( $"The Original Array: {arrPerson[0].Name}, {arrPerson[1].Name}" );
    Console.WriteLine( $"The Shallow Copy: {arrPersonClone[0].Name}, {arrPersonClone[1].Name}" );
    
    结果:

    The Original Array: Jack, Amy
    The Shallow Copy: Peter, Amy
    
    The Original Array: Peter, Amy
    The Shallow Copy: Peter, Amy
    
    The Original Array: NameChanged, PersonChanged
    The Reference Copy: NameChanged, PersonChanged
    

    2。浅层副本保留元素的原始引用。

    如果我们更改浅拷贝中元素的属性,则原始数组将受到影响,因为
    The Original Array: Jack, Amy
    The Shallow Copy: Peter, Amy
    
    // Create a new shallow copy.
    arrPersonClone = (Person[]) arrPerson.Clone();
    
    // Change the name of the first person in the shallow copy.
    arrPersonClone[0].Name = "Peter";
    
    // Display the contents of all arrays.
    Console.WriteLine( "After changing the Name property of the first element in the Shallow Copy" );
    Console.WriteLine( $"The Original Array: {arrPerson[0].Name}, {arrPerson[1].Name}" );
    Console.WriteLine( $"The Shallow Copy: {arrPersonClone[0].Name}, {arrPersonClone[1].Name}" );
    
    The Original Array: Peter, Amy
    The Shallow Copy: Peter, Amy
    
    // Create a reference copy.
    var arrPersonR = arrPerson;
    
    // Change the name of the first person.
    arrPersonR[0].Name = "NameChanged";
    // Replace the second person.
    arrPersonR[1] = new Person(){ Name = "PersonChanged" };
    
    // Display the contents of all arrays.
    Console.WriteLine( "After changing the reference copy:" );
    Console.WriteLine( $"The Original Array: {arrPerson[0].Name}, {arrPerson[1].Name}" );
    Console.WriteLine( $"The Reference Copy: {arrPersonR[0].Name}, {arrPersonR[1].Name}" );
    
    The Original Array: NameChanged, PersonChanged
    The Reference Copy: NameChanged, PersonChanged
    
    void Main()
    {
        // Create 2 Persons.
        var person1 = new Person(){ Name = "Jack" };
        var person2 = new Person(){ Name = "Amy" };
    
        // Create a Person array.
        var arrPerson = new Person[] { person1, person2 };
    
        // ----------- 1. A shallow copy copies elements. -----------
    
        // Create a shallow copy.
        var arrPersonClone = (Person[]) arrPerson.Clone();
    
        // Replace an element in the shallow copy.
        arrPersonClone[0] = new Person(){Name = "Peter"};
    
        // Display the contents of all arrays.
        Console.WriteLine( "After replacing the first element in the Shallow Copy:" );
        Console.WriteLine( $"The Original Array: {arrPerson[0].Name}, {arrPerson[1].Name}" );
        Console.WriteLine( $"The Shallow Copy: {arrPersonClone[0].Name}, {arrPersonClone[1].Name}" );
    
        Console.WriteLine( "\n" );
    
        // ----------- 2. A shallow copy retains the original references of the elements. -----------
    
        // Create a new shallow copy.
        arrPersonClone = (Person[]) arrPerson.Clone();
    
        // Change the name of the first person in the shallow copy.
        arrPersonClone[0].Name = "Peter";
    
        // Display the contents of all arrays.
        Console.WriteLine( "After changing the Name property of the first element in the Shallow Copy:" );
        Console.WriteLine( $"The Original Array: {arrPerson[0].Name}, {arrPerson[1].Name}" );
        Console.WriteLine( $"The Shallow Copy: {arrPersonClone[0].Name}, {arrPersonClone[1].Name}" );
    
        Console.WriteLine( "\n" );  
    
        // ----------- 2. The equal sign. -----------
    
        // Create a reference copy.
        var arrPersonR = arrPerson;
    
        // Change the name of the first person.
        arrPersonR[0].Name = "NameChanged";
        // Replace the second person.
        arrPersonR[1] = new Person(){ Name = "PersonChanged" };
    
        // Display the contents of all arrays.
        Console.WriteLine( "After changing the reference copy:" );
        Console.WriteLine( $"The Original Array: {arrPerson[0].Name}, {arrPerson[1].Name}" );
        Console.WriteLine( $"The Reference Copy: {arrPersonR[0].Name}, {arrPersonR[1].Name}" );
    }
    
    class Person
    {
        public string Name {get; set;}
    }