Tôi nghi ngờ sự hiểu biết của mình về ngữ nghĩa System.Collection.Generic.IReadOnlyCollection<T>
và nghi ngờ cách thiết kế bằng các khái niệm như chỉ đọc và không thay đổi. Hãy để tôi mô tả hai bản chất tôi nghi ngờ giữa bằng cách sử dụng documentation, trong đó nêu rõTính không thay đổi/ngữ nghĩa chỉ đọc (cụ thể C# IReadOnlyCollection <T>)
Đại diện cho một bộ sưu tập mạnh mẽ, chỉ đọc các phần tử.
Tùy thuộc vào việc tôi nhấn mạnh từ 'Đại diện' hoặc 'read-only' (khi phát âm trong đầu tôi, hoặc out loud nếu đó là phong cách của bạn) Tôi có cảm giác như những thay đổi câu có nghĩa:
- Khi tôi nhấn mạnh 'chỉ đọc', tài liệu được định nghĩa trong quan điểm bất biến quan sát của tôi (một thuật ngữ được sử dụng trong Eric Lippert's article), có nghĩa là thực hiện giao diện có thể làm miễn là không có đột biến hiển thị công khai †.
- Khi tôi nhấn mạnh 'Đại diện', tài liệu định nghĩa (theo ý kiến của tôi, một lần nữa) một mặt tiền bất biến (một lần nữa được mô tả trong bài viết của Eric Lippert), đó là một dạng yếu hơn, có thể xảy ra đột biến, nhưng không thể thực hiện được người dùng. Ví dụ: thuộc tính loại
IReadOnlyCollection<T>
làm rõ người dùng (nghĩa là người nào đó mã hóa với loại khai báo) rằng anh ấy không thể sửa đổi bộ sưu tập này. Tuy nhiên, không rõ ràng là liệu kiểu khai báo có phải là chính nó có thể sửa đổi bộ sưu tập hay không. - Vì mục đích hoàn chỉnh: Giao diện không mang bất kỳ ngữ nghĩa nào khác ngoài ngữ nghĩa được mang bởi chữ ký của các thành viên. Trong trường hợp này, sự bất biến quan sát hoặc mặt tiền phụ thuộc vào việc triển khai thực hiện (không chỉ là việc thực hiện-phụ thuộc vào giao diện mà phụ thuộc vào từng trường hợp).
Tùy chọn đầu tiên thực sự là giải thích ưa thích của tôi, mặc dù hợp đồng này có thể dễ dàng bị hỏng, ví dụ: bằng cách xây dựng một ReadOnlyCollection<T>
từ một mảng của T
và sau đó đặt giá trị vào mảng trình bao bọc.
Các BCL có giao diện tuyệt vời cho mặt tiền không thay đổi, chẳng hạn như IReadOnlyCollection<T>
, IReadOnlyList<T>
và có lẽ thậm chí IEnumerable<T>
, vv Tuy nhiên, tôi thấy tính bất biến quan sát cũng rất hữu ích và như xa như tôi biết, không có bất kỳ giao diện trong Carring BCL ý nghĩa này (hãy chỉ cho họ biết nếu tôi sai). Nó có ý nghĩa rằng chúng không tồn tại, bởi vì dạng bất biến này không thể được thực thi bởi một khai báo giao diện, chỉ bởi những người thực hiện (một giao diện có thể mang ngữ nghĩa, như tôi sẽ hiển thị bên dưới). Ngoài ra: Tôi rất muốn có khả năng này trong một phiên bản C# trong tương lai!
Ví dụ: (có thể bỏ qua) Tôi thường xuyên phải thực hiện một phương pháp mà được như là đối số một bộ sưu tập được sử dụng bởi thread khác là tốt, nhưng phương pháp này đòi hỏi phải có bộ sưu tập không được sửa đổi trong suốt của nó thực hiện và do đó tôi khai báo tham số là loại IReadOnlyCollection<T>
và tự vỗ về suy nghĩ rằng tôi đã đáp ứng các yêu cầu. Sai ... Để người gọi chữ ký giống như phương pháp hứa hẹn không thay đổi bộ sưu tập, không có gì khác và nếu người gọi nhận giải thích thứ hai về tài liệu (mặt tiền), anh ta có thể nghĩ rằng đột biến được phép và phương thức câu hỏi là đề kháng với điều đó. Mặc dù có những giải pháp thông thường khác cho ví dụ này, tôi hy vọng bạn thấy rằng vấn đề này có thể là một vấn đề thực tế, đặc biệt khi những người khác đang sử dụng mã của bạn (hoặc tương lai-bạn cho vấn đề đó).
Bây giờ đến vấn đề thực tế của tôi (đã kích hoạt sự nghi ngờ về giao diện ngữ nghĩa hiện có):
Tôi muốn sử dụng quan sát không thay đổi và làm mặt tiền tính bất biến và phân biệt giữa chúng. Hai tùy chọn mà tôi đã nghĩ đến là:
- Sử dụng giao diện BCL và ghi lại mỗi lần cho dù đó là quan sát hay chỉ là mặt bất biến. Nhược điểm: Người dùng sử dụng mã như vậy sẽ chỉ tham khảo tài liệu khi nó đã quá muộn, cụ thể là khi một lỗi đã được tìm thấy. Tôi muốn dẫn họ vào hố thành công; tài liệu không thể làm điều đó). Ngoài ra, tôi thấy loại ngữ nghĩa này đủ quan trọng để có thể nhìn thấy trong hệ thống kiểu chứ không phải chỉ trong tài liệu.
- Xác định giao diện mang theo ngữ nghĩa bất biến quan sát một cách rõ ràng, như
IImmutableCollection<T> : IReadOnlyCollection<T> { }
vàIImmutableList<T> : IReadOnlyList<T> { }
. Lưu ý rằng các giao diện không có bất kỳ thành viên nào ngoại trừ các thành viên được thừa kế. Mục đích của các giao diện này là chỉ nói "Ngay cả loại tuyên bố cũng không thay đổi tôi!" ‡ Tôi đặc biệt nói "sẽ không" ở đây trái ngược với "không thể". Ở đây có một bất lợi: một kẻ xấu (hoặc sai lầm, để ở lại lịch sự) thực hiện không được ngăn cản phá vỡ hợp đồng này bởi trình biên dịch hoặc bất cứ điều gì thực sự. Tuy nhiên, ưu điểm là một lập trình viên đã chọn triển khai giao diện này thay vì giao diện trực tiếp kế thừa, có khả năng nhận thức được thông báo bổ sung được gửi bởi giao diện này, bởi vì lập trình viên nhận thức được sự tồn tại của giao diện này và có khả năng thực hiện nó cho phù hợp.
Tôi đang nghĩ đến việc đi với tùy chọn thứ hai nhưng sợ nó có vấn đề về thiết kế so sánh với những loại đại biểu (trong đó đã được phát minh để mang thông tin ngữ nghĩa hơn các đối tác của họ semanticless Func
và Action
) và bằng cách nào đó mà thất bại, xem ví dụ here.
Tôi muốn biết liệu bạn có gặp phải/thảo luận vấn đề này hay không, hoặc liệu tôi chỉ đang sử dụng ngữ nghĩa quá nhiều và chỉ chấp nhận các giao diện hiện tại và liệu tôi có biết các giải pháp hiện tại không BCL. Bất kỳ vấn đề thiết kế nào như những đề cập ở trên sẽ hữu ích. Nhưng tôi đặc biệt quan tâm đến các giải pháp khác mà bạn có thể (có) đưa ra cho vấn đề của tôi (đó là trong một nutshell phân biệt quan sát và mặt tiền bất biến trong cả khai báo và sử dụng).
Cảm ơn bạn trước.
† Tôi bỏ qua các đột biến của trường, v.v ... trên các phần tử của bộ sưu tập.
‡ Điều này là hợp lệ cho ví dụ tôi đã đưa ra trước đó, nhưng tuyên bố thực sự rộng hơn. Ví dụ, bất kỳ phương thức khai báo nào sẽ không thay đổi nó, hoặc một tham số của kiểu như vậy truyền tải rằng phương thức có thể mong đợi bộ sưu tập không thay đổi trong quá trình thực thi (phương pháp này không thể thay đổi bộ sưu tập, tuyên bố người ta có thể thực hiện với các giao diện hiện có), và có lẽ nhiều người khác.
Có lẽ điều này có liên quan: http: //blogs.msdn.com/b/bclteam/archive/2012/12/18/xem trước-of-bất biến-bộ sưu tập-phát hành-on-nuget.aspx –
Tôi ưu tiên sử dụng cụm từ "Không thể thay thế" như một phần của tên lớp cho các bộ sưu tập bất biến quan sát và "Chỉ đọc" là một phần của tên lớp cho mặt tiền không thể thay đổi cho các bộ sưu tập có thể thay đổi. Tôi cũng thích các lớp không thu thập với từ "Không thay đổi" trong tên của chúng là "không thay đổi", tức là các trường là tất cả các loại giá trị riêng tư chỉ đọc, hoặc là các kiểu tham chiếu chỉ đọc riêng mà chúng không thể thay đổi được. ('readonly' là từ khóa C#) (Điều này dường như cũng là quy ước được Microsoft chấp nhận, vì vậy những ngày hạnh phúc.) –
Tôi không thực sự yêu cầu những gì bạn đang yêu cầu nhưng IImmutablexxx có nghĩa là nó không thay đổi. sự thay đổi sẽ tạo ra một bộ sưu tập mới) IReadOnlyxxx chỉ ngăn người nhận thay đổi bộ sưu tập mà nhà cung cấp có thể thay đổi nó. –