2009-02-04 33 views
7

Tôi có 2 đối tượng từ cùng một loại và tôi muốn nông sao chép trạng thái này sang trạng thái khác. Trong C + + tôi có memcpy đó là tuyệt vời. Làm thế nào tôi có thể làm điều đó trong C#? Các MemberwiseClone() là không đủ tốt bởi vì nó tạo ra & trả về một đối tượng mới và tôi muốn sao chép vào một đối tượng hiện có. Tôi đã nghĩ đến việc sử dụng sự phản chiếu nhưng tôi e rằng nó sẽ quá chậm chạp đối với mã sản xuất. Tôi cũng nghĩ đến việc sử dụng một trong các serial .Net nhưng tôi nghĩ rằng họ cũng tạo ra đối tượng hơn là thiết lập một hiện tại.C# memcpy tương đương

tôi sử dụng Case:

Tôi có một mẫu đối tượng (lớp không struct) mà cần phải được cập nhật bởi một trong các trường hợp của nó (đối tượng làm bằng mẫu này)

Bất kỳ ý tưởng?

Trả lời

4

[sửa] về việc làm rõ: Theo tôi hiểu, bạn có N đối tượng, mỗi đối tượng có một tham chiếu (trực tiếp) đối tượng mẫu. Bạn muốn viết lại mẫu để tất cả các đối tượng "nhìn thấy" những thay đổi này.

Đề xuất: imlement một nhà môi giới mẫu.

class TemplateProvider 
{ 
    public MyData Template { get; set; } 
} 

Thay vì truyền mẫu, chuyển nhà cung cấp mẫu tới các đối tượng.

để đơn giản hóa cú pháp trong các thành phần, bạn có thể thêm (riêng tư/nội bộ?) property

MyData Template { get { return m_templateProvider.Template; } } 
void UpdateTemplate() { m_templateProvider.Template = 
          (MyData) this.MemberwiseClone(); } 

Nhà cung cấp mẫu cũng đơn giản hóa khóa trong các tình huống đa luồng.


Tóm lại, không có cách nào trừ khi bạn tự làm. Nhưng tại sao không tạo ra một đối tượng mới nếu bạn ghi đè lên tất cả các thuộc tính?

memcopy và các cấu trúc mức thấp tương tự không được hỗ trợ vì chúng làm giảm sự đảm bảo của môi trường.

Bản sao nông cho cấu trúc được thực hiện bằng cách gán. Đối với các lớp học, MemberwiseClone là phương pháp để làm điều đó - nhưng khi bạn nói rằng tạo ra một đối tượng mới.

Không có cách nào được xây dựng cho điều đó và vì nó có khả năng phá vỡ đóng gói nên được sử dụng cẩn thận.

Bạn có thể xây dựng một thói quen chung bằng cách sử dụng sự phản chiếu, nhưng cho dù nó hoạt động hay không phụ thuộc vào chính lớp đó. Và có, ti sẽ được so sánh chậm.

Những gì còn lại là hỗ trợ nó bằng giao diện tùy chỉnh. Bạn có thể cung cấp một thường xuyên "Shallow Copy" thường xuyên để kiểm tra giao diện và sử dụng nó, và rơi trở lại để phản ánh khi nó không. Điều này làm cho chức năng này có sẵn nói chung và bạn có thể tối ưu hóa các lớp có hiệu suất nào quan trọng sau này.

6

Trong C# (và trong C++ quá), không có sự khác biệt giữa "đối tượng mới" và "bản sao đối tượng hiện có" miễn là tất cả các thành viên của họ bằng nhau.

Given:

Int32 a = 5; 

, cả hai hoạt động:

Int32 b = 5; 
Int32 b = a; 

mang lại kết quả tương tự.

Như đã nêu trong MSDN reference:

Phương pháp MemberwiseClone tạo ra một bản sao cạn bằng cách tạo ra một đối tượng mới, và sau đó sao chép các lĩnh vực không tĩnh của đối tượng vãng lai cho các đối tượng mới.

Nếu một trường là một loại giá trị, một bản sao từng bit của trường được thực hiện.

Nếu trường là loại tham chiếu, tham chiếu sẽ được sao chép nhưng đối tượng được giới thiệu không phải là; do đó, đối tượng gốc và bản sao của nó tham chiếu đến cùng một đối tượng.

, tức là nó chỉ giống như memcpy() trong C++

1

Tôi đoán bạn chỉ có thể làm điều gì đó như:

YourObjectType A = new YourObjectType(); 
YourObjectType B = a.MemberwiseClone(); 

này sẽ tạo ra một đối tượng mới trong phương pháp MemberwiseClone một làm cho B đối tượng tham chiếu nó. Tôi đoán nó phục vụ cho mục đích của bạn.

+0

Ông muốn biết, làm thế nào người ta có thể sao chép nội dung của một đối tượng A * vào * một đối tượng B hiện có, trọng tất cả các nội dung của nó. MemberwiseClone tạo một đối tượng * mới *. –

0

tôi không thể sử dụng một đối tượng mới được tạo ra, vì tôi thích mẫu đối tượng phải được thay đổi theo tình trạng của một trong những trường hợp của nó (tức là ví dụ làm mẫu mà)

+0

Tôi vẫn muốn một mức độ gián tiếp khác (ví dụ: "trình lấy mẫu") thay vì cập nhật đối tượng được chia sẻ, nhưng phải thừa nhận rằng đó là "chỉ là một câu hỏi về hương vị" – peterchen

0

Khi tôi nghĩ về nó - đó là rất thú vị khi nhìn vào mã của việc thực hiện phương thức MemberWiseClone() và xem cách Microsoft giải quyết câu hỏi của tôi.

0

Chuyển nhượng một cấu trúc khác, cho tất cả ý định và mục đích, hoạt động chính xác như memcpy trong C++ trên đối tượng POD.

Nếu bạn cảm thấy rằng điều này không áp dụng trong trường hợp của bạn thì tôi có thể đảm bảo với bạn rằng mã C++ của bạn không phù hợp tiêu chuẩn (tức là chứa các lỗi dưới dạng hành vi không xác định). Vui lòng chỉ định (trong câu hỏi) tác dụng bạn muốn đạt được. Điều này sẽ hữu ích hơn nói về việc sao chép hành vi không xác định bằng ngôn ngữ khác.

+0

vui lòng xem chỉnh sửa của tôi trong câu hỏi –

1
namespace WindowsFormsApplication7 
{ 

    [Serializable] // just put this in your class 
    class Mate 
    { 
     public string SomeProperty { get; set; } 
    } 

    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 


      var mA = new Mate(); 
      mA.SomeProperty = "Hey"; 

      var vf = new BinaryFormatter(); 
      var ns = new MemoryStream(); 
      vf.Serialize(ns, mA); 
      byte[] vytes = ns.ToArray(); 


      var vfx = new BinaryFormatter(); 
      var nsx = new MemoryStream();    
      nsx.Write(vytes, 0, vytes.Length); 
      nsx.Seek(0, 0); 
      var mB = (Mate)vfx.Deserialize(nsx); 

      mA.SomeProperty = "Yo"; 

      MessageBox.Show(mA.SomeProperty); // Yo 
      MessageBox.Show(mB.SomeProperty); // Hey 
     } 
    } 
} 
1
namespace WindowsFormsApplication7 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 

      var dt = new DataTable(); 
      dt.Columns.Add("lastname", typeof(string)); 
      dt.Columns.Add("firstname", typeof(string)); 

      dt.Rows.Add("lennon", "john"); 
      dt.Rows.Add("mccartney", "paul"); 


      var ms = new MemoryStream(); 
      var bf = new BinaryFormatter(); 
      bf.Serialize(ms, dt); 
      byte[] bytes = ms.ToArray(); 



      var bfx = new BinaryFormatter(); 
      var msx = new MemoryStream(); 
      msx.Write(bytes, 0, bytes.Length); 
      msx.Seek(0, 0); 


      // doesn't just copy reference, copy all contents 
      var dtx = (DataTable)bfx.Deserialize(msx); 


      dtx.Rows[0]["lastname"] = "Ono"; 


      // just copy reference 
      var dty = dt; 

      dty.Rows[0]["lastname"] = "Winston"; 

      MessageBox.Show(dt.Rows[0]["lastname"].ToString()); // Winston 
      MessageBox.Show(dtx.Rows[0]["lastname"].ToString()); // Ono 
      MessageBox.Show(dty.Rows[0]["lastname"].ToString()); // Winston 

     } 
    } 
}