2016-05-13 12 views
5

Tôi đã triển khai phương pháp sao chép sâu bằng cách sử dụng hàm tạo bản sao trong C#. Để xác minh rằng nó hoạt động, tôi đang thử nghiệm nó bằng cách so sánh các kết quả của serializing một đối tượng và bản sao của nó. Việc serialization được thực hiện theo một đối tượng chung chung T. Tôi cũng đã thử nó theo một đối tượng cụ thể và nhận được kết quả tương tự.Serialization sửa đổi nội dung của đối tượng gốc trong C#

Tôi có một phương pháp để serializing đối tượng vào mảng byte

private byte[] ObjectToBytes(T obj) 
{ 
    BinaryFormatter formatter = new BinaryFormatter(); 
    using (MemoryStream stream = new MemoryStream()) 
    { 
     formatter.Serialize(stream, obj); 
     stream.Seek(0, SeekOrigin.Begin); 
     return stream.ToArray(); 
    } 
} 

Các mã sau hoạt động tốt.

T original = this.GetNewThing(); 
T clone = original.DeepClone(); 

// serialize after cloning 
byte[] originalBytes = ObjectToBytes(original); 
byte[] cloneBytes = ObjectToBytes(clone); 

bool equal = true; 
for (int i = 0; i < originalBytes.Length; i++) 
{ 
    if(originalBytes[i] != cloneBytes[i] 
    { 
     equal = false; 
     break; 
    } 
} 
equal == true; // True! 

Tuy nhiên, khi tôi chuyển thứ tự khi các đối tượng được tuần tự hóa, các mảng byte không còn bằng nhau nữa.

// serialize before cloning 
T original = this.GetNewThing(); 
byte[] originalBytes = ObjectToBytes(original); 

T clone = original.DeepClone(); 
byte[] cloneBytes = ObjectToBytes(clone); 

bool equal = true; 
for (int i = 0; i < originalBytes.Length; i++) 
{ 
    if(originalBytes[i] != cloneBytes[i] 
    { 
     equal = false; 
     break; 
    } 
} 
equal == true; // False! 

Tại sao thứ tự serialization ảnh hưởng đến điều này? Nó có liên quan đến các đối tượng BinaryFormatter hoặc MemoryStream không?

EDIT:

Dưới đây là những gì các phương pháp nhân bản sâu trông giống như

public MyClass DeepClone() 
{ 
    return new MyClass(this); 
} 

và các nhà xây dựng nó sử dụng vẻ bề ngoài như thế này

protected MyClass(MyClass myClass) 
{ 
    if (myClass == null) 
     throw new ArguementNullException("myclass"); 

    this.number = myClass.Number; 
    this.number2 = myClass.Number2; 
    this.number3 = myClass.Number3; 
} 

Đối tượng là không có nghĩa là phức tạp. Tất cả các giá trị được sao chép là các loại giá trị, do đó không có loại tham chiếu nào cần phải lo lắng.

+6

Vui lòng đăng phương thức DeepClone .. Có thể vấn đề là –

+0

Có thể phải làm với độ phức tạp của các đối tượng - hãy kiểm tra điều này: http://stackoverflow.com/questions/5017274/binaryformatter-and-deserialization-complex -objects – Clay

+0

Hãy nghĩ rằng chúng ta có thể cần phải xem toàn bộ 'MyClass'. Ngoài ra, nó không có trạng thái, vậy tại sao 'ObjectToBytes' là một phương thức cá thể riêng và không phải là tĩnh? Tôi nghĩ rằng nó có thể hữu ích nếu bạn có thể định dạng một mã ví dụ đầy đủ có thể được cắt/dán vào, nói, LinqPad. –

Trả lời

4

DeepClone, hoặc một cái gì đó mà họ gọi đến lượt nó, dường như được thay đổi trạng thái của đối tượng nguồn của bạn.

+0

DeepClone thay đổi đối tượng nguồn bằng cách truy cập một thuộc tính không được đặt cho đến lần truy cập đầu tiên. Khi tôi sao chép trước khi tạo các mảng byte này là tốt, bởi vì cả hai thuộc tính được khởi tạo trong bản sao sâu. Tạo mảng byte trước khi sao chép không làm cho thuộc tính này được khởi tạo và tuần tự hóa không nhận các giá trị khởi tạo (thuộc tính là một kiểu giá trị, do đó thay vào đó nó chọn các giá trị mặc định). – Danny

1

Bạn phải thay đổi phương pháp ObjectToBytes như sau:

private byte[] ObjectToBytes(Object obj) 
    { 
     if(obj == null) 
      return null; 

     BinaryFormatter bf = new BinaryFormatter(); 
     using(MemoryStream ms = new MemoryStream()) { 
      bf.Serialize(ms, obj); 

      return ms.ToArray(); 
     } 
    } 

Hy vọng nó giúp

+0

Bạn có thể giải thích cách bạn nghĩ điều này sẽ giúp ích không? – adv12

+0

@ adv12 bởi vì nó là một thực tế xấu thay đổi vị trí dòng trước .ToArray. Đó là một thử, nhưng tôi muốn xem triển khai DeepClone. – RobertoB

+0

Tôi đã xóa cuộc gọi không cần thiết thành 'Tìm kiếm 'trong mã của tôi. Nó không khắc phục được sự cố. Nó cũng không gây ra bất kỳ vấn đề gì khi tôi gỡ bỏ nó vì vậy tôi sẽ bỏ nó ra. – Danny

Các vấn đề liên quan