1つのオブジェクトを別のオブジェクトにコピーするこれら2つの方法に少し慣れています。私は混乱しており、ディープコピーとシャローコピーの大きな違いを見つけることができません。 。 ->
class A
{
public int a = 0;
public void display()
{
Console.WriteLine("The value of a is " + a);
}
}
class Program
{
static void Main(string[] args)
{
A ob1 = new A();
ob1.a = 10;
ob1.display();
A ob2 = new A();
ob2 = ob1;
ob2.display();
Console.Read();
}
}
これは浅いコピーですか、それとも深いコピーですか?誰でも理由を答えてください。ディープコピーの場合、オブジェクトコピーの同じジョブを実行するこのプログラムの浅いコピーのコードを提供してください。
上記が浅いコピーである場合、これでさえ浅いコピーでなければなりません->
A ob1 = new A();
ob1.a = 10;
ob1.display();
A ob2 = ob1;
ob2.a = 444;
ob1.display();
リンクから こちら
浅いコピーの複製は可能な限り少なくします。コレクションの浅いコピーは、要素ではなくコレクション構造のコピーです。浅いコピーでは、2つのコレクションが個々の要素を共有するようになりました。
ディープコピーはすべてを複製します。コレクションのディープコピーは、元のコレクションのすべての要素が複製された2つのコレクションです。
あなたの例は浅いコピーを作成しています。
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 = new A();
ob1.a = 10;
A ob2 = new A();
ob2.a = ob1.a;
ob1.a = 5; // <-- If you see value of ob2.a after this line, it will be 10.
私の意見では、厳密な浅いコピーまたは深いコピーではありません。定義する必要がある場合、浅いコピーと言います。
ob2 = ob1;このコードは、両方が同じオブジェクトを参照する2つのオブジェクト参照を作成します。したがって、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
これは浅いコピーでも深いコピーでもありません。これは参照コピーです。説明させてください。変数には2つのタイプがあります。値のタイプと参照のタイプです。
値型は、変数の実際の値を保持するコンピューターメモリ内の(名前の付いた)場所です。例: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という変数が作成され、Aクラスのインスタンスが作成され、そのクラスの場所がob1に保存されます。
ob1.a = 10;
ob1.display();
これにより、Aクラス内の変数aが変更されます。次に、display()メソッドを呼び出します
A ob2 = new A();
ここでは、ob2という変数を作成し、クラスAのインスタンスを作成し、その場所をob2に割り当てます。
これで、Aの2つのクラスインスタンスと、それぞれがそれらの1つを指している2つの変数がメモリ内にあります。ここからが興味深い部分です。ob2= ob1;
変数ob2には変数ob1の値が割り当てられます。 ob1にはAの最初のインスタンスのメモリ位置が含まれているため、ob1とob2の両方がメモリ内の同じ位置を指します。それらのいずれかを使用して何かを行うことは、もう一方とまったく同じシンを行うことです。
ob2 = ob1は、参照をコピーしていることを意味します。
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;
}
}
@docesamからの回答と@Will Yuからの回答の一部を支持します。
これは浅いコピーでも深いコピーでもありません。これは参照コピーです。 -ドセサム
ob2 = ob1;このコードは、両方が同じオブジェクトを参照する2つのオブジェクト参照を作成します。したがって、ob1を介して行われたオブジェクトへの変更は、ob2の以降の使用に反映されます。 -ウィル・ウィル
MSDN(備考を参照) によると:
配列の浅いコピーは、それらが参照型または値型であるかどうかにかかわらず、配列の要素のみをコピーしますが、参照が参照するオブジェクトはコピーしません。新しい配列の参照は、元の配列の参照が指すのと同じオブジェクトを指します。
ここで、注意すべきことが2つあります。
次に、これら2つを個別に説明します。
まず、Person
プロパティを持つName
クラスを作成します。
_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。浅いコピーは要素をコピーします。
浅いコピーの最初の要素をreplaceする場合、元の配列は影響を受けません。
_// 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
_
2。浅いコピーは、要素の元の参照を保持します。
浅いコピーの要素のプロパティをchangeすると、この要素が参照するオブジェクトはコピーされないため、元の配列が影響を受けます。
_// 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
_
結論として、_ob2 = ob1
_は浅いコピーではなく、参照コピーです。
遊ぶための完全なコード:
_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;}
}
_
2番目のオブジェクトに割り当てた後、最初のオブジェクトのプロパティを変更するには、さらに2、3行のコードを記述します。次に、両方のオブジェクトでdisplayメソッドを呼び出して、結果を確認します。これにより、実際には浅いコピーであることがわかります。