Đây là một trường hợp trừu tượng bị rò rỉ. Thuộc tính thực sự là một phương thức, các trình truy cập get và set cho một indexer được biên dịch thành các phương thức get_Index () và set_Index. Trình biên dịch thực hiện một công việc tuyệt vời là che giấu sự thật đó, nó sẽ tự động dịch một nhiệm vụ cho một thuộc tính sang phương thức set_Xxx () tương ứng chẳng hạn.
Nhưng điều này sẽ xuất hiện khi bạn truyền một tham số phương thức bằng tham chiếu. Điều đó yêu cầu trình biên dịch JIT chuyển một con trỏ đến vị trí bộ nhớ của đối số được truyền vào. Vấn đề là, không có một, việc gán giá trị của một thuộc tính yêu cầu gọi phương thức setter. Phương thức được gọi không thể cho biết sự khác biệt giữa một biến được truyền và một thuộc tính được truyền vào và do đó không thể biết liệu một cuộc gọi phương thức có được yêu cầu hay không.
Đáng chú ý là điều này thực sự hoạt động trong VB.NET. Ví dụ:
Class Example
Public Property Prop As Integer
Public Sub Test(ByRef arg As Integer)
arg = 42
End Sub
Public Sub Run()
Test(Prop) '' No problem
End Sub
End Class
Trình biên dịch VB.NET giải quyết vấn đề này bằng cách tự động tạo mã này cho phương thức Run, được thể hiện bằng C #:
int temp = Prop;
Test(ref temp);
Prop = temp;
Đó là giải pháp thay thế bạn cũng có thể sử dụng. Không hoàn toàn chắc chắn tại sao nhóm C # không sử dụng cách tiếp cận tương tự. Có thể vì họ không muốn ẩn các cuộc gọi getter và setter có thể tốn kém. Hoặc hành vi hoàn toàn không thể phân biệt được mà bạn sẽ nhận được khi setter có các tác dụng phụ làm thay đổi giá trị thuộc tính, chúng sẽ biến mất sau khi gán. Sự khác biệt cổ điển giữa C # và VB.NET, C # là "không có gì ngạc nhiên", VB.NET là "làm cho nó hoạt động nếu bạn có thể".