2011-09-02 26 views
9

thể trùng lặp:
Modify Struct variable in a DictionaryChuyển nhượng lĩnh vực/tài sản trong một cấu trúc

Tại sao nó rằng

MyStruct test = new MyStruct(); 
    test.Closed = true; 

Các công trình lớn, nhưng

MyDictionary[key].Closed = true; 

Hiển thị lỗi "Không thể sửa đổi biểu thức vì nó không phải là biến" tại thời gian biên dịch?

Tại sao khác nhau về nhiệm vụ trong hai trường hợp này?

Lưu ý: MyDictionary là loại <int, MyStruct>

Mã cho struct:

public struct MyStruct 
{ 
    //Other variables 
    public bool Isclosed; 
    public bool Closed 
    { 
     get { return Isclosed; } 
     set { Isclosed = value; } 
    } 
//Constructors 
} 
+0

Hiển thị mã hơn .. – Zabba

+0

@Zabba, được chỉnh sửa để có thêm mã. – soandos

+0

Nhận xét của người trả lời xin vui lòng? – soandos

Trả lời

12

MyDictionary[key] lợi nhuận một cấu trúc, nó thực sự đang trở lại một bản sao của đối tượng trong bộ sưu tập, không phải là đối tượng thực sự là điều xảy ra khi bạn sử dụng một lớp. Đây là những gì trình biên dịch cảnh báo bạn.

Để làm việc xung quanh này, bạn sẽ phải tái thiết lập MyDictionary[key], có lẽ như thế này:

var tempObj = MyDictionary[key]; 
tempObj.Closed = true; 
MyDictionary[key] = tempObj; 
+0

Nhưng sau đó tôi sẽ cần gọi lại toàn bộ hàm tạo không? Không có cách nào để thay đổi một phần của cấu trúc trong tình huống này? – soandos

+0

Tôi đã sửa đổi ví dụ của mình để sử dụng lại cùng một đối tượng thay vì tạo một đối tượng mới. – Keith

+1

@soandos struct luôn được sao chép khi được truyền giữa các phương thức, vì vậy "toàn bộ hàm tạo" đang diễn ra mọi lúc (ví dụ khi bạn truy cập cấu trúc của mình bằng khóa trong dict đó), đó là lý do tại sao đề xuất không có cấu trúc lớn hơn 16 byte –

1

Thay đổi cấu trúc là một lớp thay vì ...

class Program 
{ 
    static void Main(string[] args) 
    { 
     dic = new Dictionary<int, MyStruct>(); 

     MyStruct s = new MyStruct(){ Isclosed=false}; 

     dic.Add(1,s); 

     dic[1].Isclosed = true; 

     Console.WriteLine(dic[1].Isclosed.ToString()); //will print out true... 
     Console.Read(); 
    } 

    static Dictionary<int, MyStruct> dic; 

    public class MyStruct 
    { 
     public bool Isclosed; 
     public bool Closed 
     { 
      get { return Isclosed; } 
      set { Isclosed = value; } 
     } 
    } 
} 
+0

Tôi biết cấu trúc có hiệu quả hơn khi xử lý một số đối tượng có chứa các trường như cấu trúc của bạn nhưng nếu bạn chỉ cần khởi tạo một vài đối tượng thì tạo một lớp sẽ giúp bạn lưu một số dòng mã :) –

+0

Khi sử dụng cấu trúc trường tiếp xúc với các bộ sưu tập tích hợp khác với mảng, người ta phải sao chép cấu trúc, sửa đổi nó, và sau đó lưu trữ nó trở lại. Một phiền toái, nhưng ngữ nghĩa có thể dự đoán được; 'dic [1] .Isclosed' sẽ luôn độc lập với' dic [0] .Isclosed'. Nói 'dic [0] = dic [1];' sẽ sao chép trạng thái 'dic [0]' mà không gắn hai mục với nhau. Nếu người ta sử dụng một lớp có thể thay đổi, người ta có thể viết 'dic [1] .Isclosed = true;' nhưng điều đó không có nghĩa là làm như vậy sẽ mang lại hành vi mong muốn. Một đối tượng đóng gói trạng thái của nó trong trạng thái của các đối tượng có thể thay đổi được tổ chức trong một bộ sưu tập phải ... – supercat

+0

... thường tránh cho phép bất kỳ tham chiếu nào đến các đối tượng được đề cập tiếp cận mã bên ngoài.Điều này có nghĩa là sao chép bất kỳ dữ liệu đến được lưu trữ trong bộ sưu tập, và sao chép hoặc gói dữ liệu bất kỳ từ nó. Structs tự động thực hiện sao chép phòng thủ khi đọc hoặc ghi dữ liệu, nhưng thao tác sao chép trên cấu trúc của bất kỳ kích thước nào rẻ hơn nhiều so với các thao tác trên một lớp có cùng kích thước. Sự khác biệt về chi phí là lớn nhất đối với các cấu trúc nhỏ, nhưng vẫn có ý nghĩa cho đến khi cấu trúc trở nên rất lớn. – supercat

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