Hành vi cực kỳ giống với Array.Resize
phương thức trong .NET. Để hiểu những gì đang diễn ra, có thể hữu ích khi xem lịch sử của .
mã thông báo trong C, C ++, Java, C # và Swift.
Trong C, một cấu trúc không có gì khác hơn là tổng hợp các biến. Áp dụng .
một biến của kiểu cấu trúc sẽ truy cập vào một biến được lưu trữ trong cấu trúc. Con trỏ tới các đối tượng không giữ tập hợp các biến, nhưng xác định chúng. Nếu một con trỏ xác định cấu trúc, ->
toán tử có thể được sử dụng để truy cập vào một biến được lưu trữ trong cấu trúc được xác định bởi con trỏ.
Trong C ++, các cấu trúc và các lớp không chỉ tổng hợp các biến mà còn có thể đính kèm mã vào chúng. Sử dụng .
để gọi một phương thức sẽ trên một biến yêu cầu phương thức đó hành động theo chính nội dung của biến đó ; sử dụng ->
trên một biến xác định một đối tượng sẽ yêu cầu phương thức đó hành động theo đối tượng được xác định bởi biến đó.
Trong Java, tất cả các loại biến tùy chỉnh chỉ cần xác định các đối tượng và gọi một phương thức trên một biến sẽ cho phương thức biết đối tượng nào được xác định bởi biến. Các biến không thể trực tiếp giữ bất kỳ loại dữ liệu tổng hợp nào, cũng như không có bất kỳ phương tiện nào mà một phương thức có thể truy cập vào một biến mà nó được gọi. Những hạn chế này, mặc dù hạn chế về mặt ngữ nghĩa, đơn giản hóa rất nhiều thời gian chạy và tạo điều kiện cho việc xác thực mã byte; sự đơn giản hóa như vậy đã làm giảm chi phí tài nguyên của Java tại thời điểm thị trường nhạy cảm với các vấn đề như vậy và do đó đã giúp nó có được lực kéo trên thị trường. Chúng cũng có nghĩa là không cần mã thông báo tương đương với mã .
được sử dụng trong C hoặc C ++. Mặc dù Java có thể đã được sử dụng ->
giống như C và C ++, nhưng những người tạo đã chọn sử dụng ký tự đơn.
vì nó không cần thiết cho bất kỳ mục đích nào khác.
Trong C # và các ngôn ngữ .NET khác, các biến có thể xác định các đối tượng hoặc giữ các kiểu dữ liệu tổng hợp trực tiếp. Khi được sử dụng trên một biến của kiểu dữ liệu tổng hợp, sẽ .
tác động đến nội dung của biến đó; khi được sử dụng trên một biến của kiểu tham chiếu, .
tác động lên đối tượng được xác địnhbởi nó. Đối với một số loại hoạt động, sự khác biệt về ngữ nghĩa không đặc biệt quan trọng, nhưng đối với các hoạt động khác thì không. Các tình huống có vấn đề nhất là những tình huống trong đó phương thức của kiểu dữ liệu tổng hợp sẽ sửa đổi biến mà nó được gọi, được gọi trên một biến chỉ đọc. Nếu một nỗ lực được thực hiện để gọi một phương thức trên một giá trị hoặc biến chỉ đọc, trình biên dịch thường sẽ sao chép biến đó, hãy để phương thức hành động theo đó và loại bỏ biến đó. Điều này thường an toàn với các phương thức chỉ đọc biến, nhưng không an toàn với các phương thức ghi vào nó. Thật không may, .does vẫn chưa có bất kỳ phương tiện nào cho biết phương pháp nào có thể được sử dụng một cách an toàn với sự thay thế đó và phương pháp nào không thể.
Trong Swift, các phương thức trên tổng hợp có thể chỉ ra rõ ràng liệu chúng có sửa đổi biến mà chúng được gọi hay không và trình biên dịch sẽ cấm sử dụng các phương thức biến đổi trên các biến chỉ đọc (thay vì chúng biến đổi các bản sao tạm thời của biến đó bị loại bỏ). Do sự khác biệt này, sử dụng .
mã thông báo để gọi các phương thức sửa đổi các biến mà chúng được gọi sẽ an toàn hơn nhiều trong Swift so với .NET. Thật không may, thực tế là cùng một .
mã thông báo được sử dụng cho mục đích đó để hành động theo một đối tượng bên ngoài được xác định bởi một biến có nghĩa là khả năng gây nhầm lẫn vẫn còn.
Nếu có một cỗ máy thời gian và quay trở lại việc tạo ra C # và / hoặc Swift, người ta có thể tránh được nhiều sự nhầm lẫn xung quanh các vấn đề như vậy bằng cách sử dụng các ngôn ngữ .
và ->
mã thông báo theo cách gần gũi hơn với việc sử dụng C ++. Các phương thức của cả hai loại tổng hợp và tham chiếu có thể sử dụng .
để hành động theo biến mà chúng được gọi và ->
hành động theo một giá trị (đối với vật liệu tổng hợp) hoặc vật được xác định qua đó (đối với loại tham chiếu). Không ngôn ngữ nào được thiết kế theo cách đó, tuy nhiên.
Trong C #, cách thực hành thông thường đối với một phương thức để sửa đổi một biến mà nó được gọi là truyền biến đó dưới dạng ref
tham số cho một phương thức. Do đó, việc gọi Array.Resize(ref someArray, 23);
khi someArray
xác định một mảng gồm 20 phần tử sẽ gây ra someArray
việc xác định một mảng mới gồm 23 phần tử, mà không ảnh hưởng đến mảng ban đầu. Việc sử dụng ref
làm rõ rằng phương thức nên được dự kiến sẽ sửa đổi biến mà nó được gọi. Trong nhiều trường hợp, thật thuận lợi khi có thể sửa đổi các biến mà không phải sử dụng các phương thức tĩnh; Địa chỉ Swift có nghĩa là bằng cách sử dụng .
cú pháp. Nhược điểm là nó mất đi sự rõ ràng về phương thức nào tác động đến các biến và phương thức nào tác động đến các giá trị.