2014-12-31 3 views
3

B 클래스에 A 클래스의 인스턴스를 저장하는 C# 코드가 있다고 가정 해 봅니다. A 클래스를 저장하는 B 클래스의 버전을 만들고 싶습니다. 따라서 B를 A 외부로 변경하면 B의 내부 A 객체 변경되지 않습니다.C#에서 다른 클래스 개체를 저장하는 클래스 개체를 얻는 방법?

class Engine 
{ 
    public int Horesepower = 500; 
} 
class Vehicle 
{ 
    public Vehicle(Engine engine) { Engine = engine; } 
    public Engine Engine; 
} 

class Program 
{ 
    static void Main(string[ ] args) 
    { 
     Engine v8 = new Engine(); 
     Vehicle monsterTruck = new Vehicle(v8); 
     v8.Horesepower = 1000; // this changes the field Engine in yugo as well 

     Console.WriteLine(monsterTruck.Engine.Horesepower); // prints 1000 instead of 500 
    } 
} 

내가 B.에 전달하지만 분명히 깊은 클론이 널리 어떤 이유로 C#에서 사용하지 않는 것 때를 클론 템플릿 다리 클래스를 사용하여 C++에서이 문제를 방지 할 수 있습니다 (왜?). 누구든지이 저장 문제에 대해 좋은 방법을 제공 할 수 있습니까?

C++ 코드 : 당신이 복제하는 개체 값 유형을 포함하고 있지만, 일반적 경우 Clone()는 사용자의 요구를 만족시킬 사용

template <typename T> 
class Wrapper{ 
public: 
    Wrapper(const Wrapper<T> &orig){if(orig.data!=nullptr)data = orig.data->clone();} 
    Wrapper(const T &origdata){data = origdata.clone();} 
    Wrapper & operator=(const Wrapper<T> &orig){...} 
    ... 
    ~T(){delete data;} 
private: 
    T *data; 
} 

class A{ 
public: 
    A():data(9){} 
    int data; 
    A *clone(){return new A(*this);} 
} 

class B{ 
public: 
    B(const Wrapper<A>& a_):ainner(a_){} 
    Wrapper<A> ainner; 
} 

int main(){ 
    A a; 
    B b(a); 
    a.data =20; 
    std::cout << b.ainner.data; // prints 9 still 
    return 0; 
} 
+2

당신은 깊은 복제를 직접 구현할 수 있습니다 도움이되기를 바랍니다이

using System; public class Program { public static void Main() { A foo = new A(); B bar = new B(foo); foo.data = 20; Console.WriteLine(bar.a.data); // prints 9 } } class A { public int data = 9; public A() { } public A(A a) { this.data=a.data; } } class B { public B(A a_) { a = new A(a_); } public A a; } 

처럼 복사 생성자를 사용하여 문제를 해결합니다. 'ICloneable' 인터페이스는 그 이유 때문에 존재합니다. (최고의 인터페이스 디자인은 아니지만 그게 뭔지.) http://msdn.microsoft.com/en-us/library/system.icloneable%28v=vs.110%29.aspx – xxbbcc

+1

내가 아는 바로는 IClonable은 얕은 복제물과 깊은 복제물을 구별하지 못합니다. – user22119

+0

'Clone()'은 일반적으로 딥 복제에 사용됩니다. 'Object.MemberwiseClone'는 이미 객체의 얕은 사본을 수행합니다. 인터페이스에 특별히 언급되지는 않았지만 설명서를 읽으면 딥 클론에 대해 설명합니다. 내가 말했듯이, 그것은 잘 설계된 인터페이스가 아닙니다. – xxbbcc

답변

3

다른 참조 유형 속성을 가진 클래스를 가질 것 (당신의 예에서와 같이) 및 얕은 복사본 (Clone()을 통해)은 단순히 참조를 복사합니다.

딥 (deep) 복사본은 참조 유형 또는 직렬화를 통해 모든 속성에 복사본 생성자를 구현하여 수행 할 수 있습니다. 깊은 복사 예를하고 Deep cloning objects

복사 생성자 :

class Engine 
{ 
    public Engine() { } 
    public Engine(Engine e) { Horesepower = e.Horesepower; } 

    public int Horesepower = 500; 
} 
class Vehicle : ICloneable 
{ 
    public Vehicle(Engine engine) { Engine = engine; } 
    public Vehicle(Vehicle v) { Engine = new Engine(v.Engine); } 

    public Engine Engine; 

    public object Clone() 
    { 
     Vehicle newVehicle = new Vehicle(this); 
     return newVehicle; 
    } 
} 
+0

직렬화가 내 문제에 대해 약간 과장된 것처럼 느껴집니다. C++ 배경에서 오는 것은 상수 매개 변수를 전달하는 것과 같이 C#에서는 필요하지 않은 무언가를 깊이 복제하는 것입니까? 비 관용적 인 코드를 작성하고 싶지 않습니다. – user22119

+0

꽤 많이 사용됩니다. 직렬화를 원하지 않으면 복사 생성자를 작성해야합니다. –

+0

직렬화는 복제를위한 매우 무거운 망치입니다. 최후의 수단이되어야합니다. 모든 코드를 제어 할 수 있어야합니다. – dodexahedron

2

은 당신이 주변에 대한 참조를 전달하는 것을 기억

직렬화는 깊은 복사를 수행하는 가장 간단한 방법이 될 것입니다. A의 인스턴스화 된 사본을 무언가에 전달하면 A의 사본을 C에 전달한 것처럼 (& a를 전달한 것처럼).

클래스는 모두 참조 유형이므로 C#에서는 복사가 명시 적으로 어딘가에서 수행되어야합니다. 다음은 익명의 생성자를 사용하여 관심있는 값을 복사하는 솔루션입니다. 마음에

static void Main(string[ ] args) 
    { 
     Engine v8 = new Engine(); 
     v8.Horesepower = 1000; // this changes the field Engine in yugo as well 
     Vehicle monsterTruck = new Vehicle(new Engine { Horesepower = v8.Horesepower }); 

     Console.WriteLine(v8.Horesepower); // prints 1000 
     Console.WriteLine(monsterTruck.Engine.Horesepower); // prints 1000 

     v8.Horesepower = 800; 
     monsterTruck.Engine.Horesepower = 1200; 

     Console.WriteLine(v8.Horesepower); // prints 800 
     Console.WriteLine(monsterTruck.Engine.Horesepower); // prints 1200 
    } 

곰이 쉬운 솔루션입니다,하지만 당신은 당신이 복사하는 클래스도 포함 할 수있는 참조 클래스의 전체 복사본을해야하는 경우가 성가신 가져옵니다. 이 경우, @ TMcKeown이 게시 한 ICloneable 솔루션은 더 안전하며 항상 견고합니다 (유지 관리한다고 가정).

+0

일회성 상황 인 경우 익명의 생성자가이 작업을 수행 할 수 있습니다. 나는이 대답에 그것을 넣을 것이다. – dodexahedron

+0

기다려 ... 당신의 의견은 내가 바라는 것과는 정반대 인 것 같습니다. 질문은 불분명하다. A의 이전 인스턴스에서 값을 복사 했습니까? 질문 코드의 주석은 아니오를 나타내는 것으로 보입니다. – dodexahedron

+0

죄송합니다, 문제를 명확히하기 위해 C# 코드를 편집했습니다. – user22119

0

또 다른 방법은 당신이

관련 문제