Sự khác biệt giữa 'được bảo vệ' và 'nội bộ được bảo vệ' là gì?


244

Ai đó có thể vui lòng giải thích cho tôi sự khác biệt giữa công cụ sửa đổi 'được bảo vệ' và 'được bảo vệ nội bộ' trong C # không? Có vẻ như họ cư xử theo cách tương tự.

Câu trả lời:


402

Công cụ sửa đổi truy cập "được bảo vệ nội bộ" là sự kết hợp của cả công cụ sửa đổi "được bảo vệ" và "bên trong".

Từ MSDN, Bộ điều chỉnh truy cập (Hướng dẫn lập trình C #) :

được bảo vệ :

Loại hoặc thành viên chỉ có thể được truy cập bằng mã trong cùng một lớp hoặc cấu trúc hoặc trong một lớp có nguồn gốc từ lớp đó.

nội bộ :

Loại hoặc thành viên có thể được truy cập bởi bất kỳ mã nào trong cùng một hội đồng, nhưng không phải từ một hội đồng khác.

bảo vệ nội bộ :

Loại hoặc thành viên có thể được truy cập bởi bất kỳ mã nào trong hội đồng mà nó được khai báo, HOẶC từ bên trong một lớp dẫn xuất trong một tổ hợp khác. Truy cập từ một hội đồng khác phải diễn ra trong một khai báo lớp xuất phát từ lớp trong đó phần tử bên trong được bảo vệ được khai báo và nó phải diễn ra thông qua một thể hiện của loại lớp dẫn xuất.

Lưu ý rằng : protected internalcó nghĩa là " protectedHOẶC internal" (bất kỳ lớp nào trong cùng một cụm hoặc bất kỳ lớp dẫn xuất nào - ngay cả khi nó ở trong một cụm khác).

... Và cho đầy đủ:

riêng tư :

Loại hoặc thành viên chỉ có thể được truy cập bằng mã trong cùng một lớp hoặc cấu trúc.

công khai :

Loại hoặc thành viên có thể được truy cập bởi bất kỳ mã nào khác trong cùng một hội đồng hoặc một hội đồng khác tham chiếu nó.

bảo vệ tư nhân :

Quyền truy cập được giới hạn trong lớp chứa hoặc các loại có nguồn gốc từ lớp chứa trong hội đồng hiện tại.
( Có sẵn từ C # 7.2 )


2
Tôi có thể có một thành viên protected internalđể nó protectedở trong hội đồng hiện tại và hoàn toàn không có sẵn bên ngoài không?
Shimmy Weitzhandler

8
Đó sẽ là "Được bảo vệ", phải không?
CAD bloke

2
@Shimmy: bạn có thể có một lớp bên trong với các phương thức được bảo vệ . Nhưng sau đó cả lớp sẽ không có sẵn từ các hội đồng bên ngoài.
M4N

1
@Shimmy hãy xem đề xuất này cho phiên bản tương lai của C # github.com/dotnet/roslyn/blob/features/privateProtected/docs/iêu
Nate Cook

@Shimmy Ít nhất CLR không hỗ trợ khái niệm giao điểm của khả năng truy cập được bảo vệ và nội bộ, nhưng ngôn ngữ C # thì không. C # chỉ hỗ trợ kết hợp hai công cụ sửa đổi truy cập.
RBT

89

protected có thể được sử dụng bởi bất kỳ lớp con từ bất kỳ lắp ráp.

protected internallà tất cả mọi thứ protected, cộng với bất cứ thứ gì trong cùng một tổ hợp có thể truy cập nó.

Điều quan trọng, nó không có nghĩa là "các lớp con trong cùng một tổ hợp" - đó là sự kết hợp của hai, không phải là giao điểm.


3
Chỉ là một FYI cho độc giả rằng CLR cũng hỗ trợ khái niệm giao điểm của khả năng tiếp cận được bảo vệ và nội bộ, nhưng C # không hỗ trợ điều này. C # chỉ hỗ trợ liên minh của hai người như được đề cập trong bài viết này.
RBT

1
Chỉ cần một FYI khác cho độc giả, "các lớp con trong cùng một hội đồng" có thể đạt được với công cụ private protectedsửa đổi truy cập được giới thiệu trong C # 7.2
LordWilmore

52

- Cập nhật câu trả lời 2019 -

Bạn có thể tìm thấy sự khác biệt trong khả năng truy cập dựa trên bảng dưới đây là có,

nhập mô tả hình ảnh ở đây


4
Câu trả lời đẹp, nó truyền đạt rất rõ sự khác biệt giữa mỗi công cụ sửa đổi truy cập.
e_i_pi

23

Trong thực tế, về phương pháp:

bảo vệ - có thể truy cập cho các lớp kế thừa, nếu không thì riêng tư.

nội bộ - công khai chỉ dành cho các lớp bên trong hội đồng, nếu không thì riêng tư.

được bảo vệ bên trong - có nghĩa là các phương thức được bảo vệ hoặc bên trong - có thể truy cập được đối với các lớp được kế thừa cho bất kỳ lớp nào trong hội đồng.


1
Tôi sẽ sử dụng HOẶC để diễn đạt nguyên nhân đó không phải là cả hai điều đó là đúng.
Brian Rasmussen

Tôi không hoàn toàn đồng ý với phần "thay đổi hành vi của lớp cơ sở" trong phần mô tả "được bảo vệ". Tôi muốn nói rằng đây là nơi bạn sử dụng "ảo" (trên lớp cơ sở) và "ghi đè" (trên lớp dẫn xuất).
M4N

Có cách nào để đánh dấu một thành viên là protectedAND internalkhông?
Shimmy Weitzhandler

@Shimmy: vâng protected internal.
abatishchev

1
@Shimmy hai năm sau, và vâng. Bây giờ có một cách trong C # 7.2. Nó được gọi là private protected docs.microsoft.com/en-us/dotnet/csharp/lingu-reference/ mẹo
Pauli Østerø

10

Vẫn còn nhiều nhầm lẫn trong việc hiểu phạm vi của các bộ truy cập "được bảo vệ bên trong", mặc dù hầu hết có định nghĩa được định nghĩa chính xác. Điều này giúp tôi hiểu được sự nhầm lẫn giữa "được bảo vệ" và "được bảo vệ nội bộ":

công cộng thực sự là công khai trong và ngoài hội đồng ( công khai bên ngoài / công cộng bên ngoài )

được bảo vệ thực sự được bảo vệ bên trong và bên ngoài lắp ráp ( bên trong được bảo vệ / bên ngoài được bảo vệ ) (không được phép trên các lớp cấp cao nhất)

private là thực sự riêng tư trong và ngoài hội đồng ( private private / private bên ngoài ) (không được phép trên các lớp cấp cao nhất)

nội bộ thực sự công khai bên trong hội đồng nhưng bị loại trừ bên ngoài hội đồng như tư nhân ( công khai nội bộ / loại trừ bên ngoài )

bảo vệ nội bộ thực sự công khai bên trong lắp ráp nhưng được bảo vệ bên ngoài lắp ráp ( bên trong công cộng / bên ngoài được bảo vệ ) (không được phép trên các lớp cấp cao nhất)

Bạn có thể thấy nội bộ được bảo vệ là một con thú rất kỳ lạ. Không trực quan.

Điều đó bây giờ đặt ra câu hỏi tại sao Microsoft không tạo ra một ( bên ngoài được bảo vệ / loại trừ bên ngoài ) hoặc tôi đoán một loại "bảo vệ riêng tư" hoặc "bảo vệ nội bộ"? cười lớn. Có vẻ không đầy đủ?

Thêm vào sự nhầm lẫn là thực tế bạn có thể lồng các thành viên lồng nhau nội bộ hoặc được bảo vệ bên trong các loại được bảo vệ, nội bộ hoặc riêng tư. Tại sao bạn sẽ truy cập vào một "nội bộ được bảo vệ" lồng trong một lớp bên trong không bao gồm quyền truy cập bên ngoài?

Microsoft cho biết các kiểu lồng nhau như vậy bị giới hạn bởi phạm vi kiểu cha của chúng, nhưng đó không phải là những gì trình biên dịch nói. Bạn có thể biên dịch các phần bên trong được bảo vệ bên trong các lớp bên trong sẽ giới hạn phạm vi chỉ cho phần lắp ráp.

Đối với tôi điều này cảm thấy như thiết kế không đầy đủ. Họ nên đơn giản hóa phạm vi của tất cả các loại thành một hệ thống xem xét rõ ràng sự kế thừa nhưng cũng bảo mật và phân cấp các loại lồng nhau. Điều này sẽ làm cho việc chia sẻ các đối tượng trở nên cực kỳ trực quan và chi tiết hơn là khám phá khả năng truy cập của các loại và thành viên dựa trên một hệ thống phạm vi không hoàn chỉnh.


1
bảo vệ riêng tư hiện đã được thêm vào C # 7.2, về cơ bản là nội bộ VÀ được bảo vệ.
Pauli Østerø

7

được bảo vệ : biến hoặc phương thức sẽ chỉ khả dụng cho các lớp con (trong bất kỳ hội đồng nào)

bảo vệ nội bộ : có sẵn cho các lớp con trong bất kỳ hội đồng nào cho tất cả các lớp trong cùng một hội đồng


3

Tôi đã đọc các định nghĩa rất rõ ràng cho các điều khoản này.

Được bảo vệ: Quyền truy cập được giới hạn trong phạm vi định nghĩa lớp và bất kỳ lớp nào kế thừa từ lớp. Loại hoặc thành viên chỉ có thể được truy cập bằng mã trong cùng một lớp hoặc cấu trúc hoặc trong một lớp có nguồn gốc từ lớp đó.

Internal: Access chỉ giới hạn ở các lớp được định nghĩa trong tập hợp dự án hiện tại. Loại hoặc thành viên chỉ có thể được truy cập bằng mã trong cùng một lớp.

Protected-Internal: Quyền truy cập được giới hạn ở lắp ráp hiện tại hoặc các loại có nguồn gốc từ lớp chứa.


1

Thành viên được bảo vệ

Thành viên được bảo vệ của một lớp chỉ có sẵn trong lớp chứa (trong đó nó đã được khai báo) và trong lớp dẫn xuất trong hội đồng và cả bên ngoài hội đồng.

Có nghĩa là nếu một lớp nằm ngoài hội đồng có thể sử dụng thành viên được bảo vệ của hội đồng khác bằng cách chỉ kế thừa lớp đó.

Chúng ta có thể tiếp xúc với thành viên được bảo vệ bên ngoài hội đồng bằng cách kế thừa lớp đó và chỉ sử dụng nó trong lớp dẫn xuất.

Lưu ý: Không thể truy cập các thành viên được bảo vệ bằng cách sử dụng đối tượng trong lớp dẫn xuất.

Thành viên nội bộ

Thành viên nội bộ của một lớp có sẵn hoặc truy cập trong hội đồng hoặc tạo đối tượng hoặc trong lớp dẫn xuất hoặc bạn có thể nói nó có thể truy cập được trên tất cả các lớp trong hội đồng.

Lưu ý: Các thành viên nội bộ không thể truy cập bên ngoài hội đồng bằng cách sử dụng tạo đối tượng hoặc trong lớp dẫn xuất.

Bảo vệ nội bộ

Bảo vệ sửa đổi truy cập nội bộ được kết hợp Bảo vệ hoặc nội bộ.

Thành viên nội bộ được bảo vệ có thể có sẵn trong toàn bộ hội đồng trong đó nó tuyên bố tạo đối tượng hoặc bằng cách kế thừa lớp đó. Và có thể được truy cập bên ngoài lắp ráp trong một lớp dẫn xuất.

Lưu ý: Thành viên được bảo vệ Nội bộ hoạt động như Nội bộ trong cùng một tổ hợp và hoạt động như Được bảo vệ bên ngoài tổ hợp.


1

công khai - Các thành viên (Hàm & Biến) được khai báo là công khai có thể được truy cập từ bất cứ đâu.

private - Các thành viên riêng không thể được truy cập từ bên ngoài lớp. Đây là công cụ xác định truy cập mặc định cho thành viên, tức là nếu bạn không chỉ định công cụ truy cập cho thành viên (biến hoặc chức năng), nó sẽ được coi là riêng tư. Do đó, chuỗi PhoneNumber; tương đương với PhoneNumber chuỗi riêng.

được bảo vệ - Các thành viên được bảo vệ chỉ có thể được truy cập từ các lớp con.

nội bộ - Nó chỉ có thể được truy cập trong cùng một hội đồng.

được bảo vệ nội bộ - Nó có thể được truy cập trong cùng một hội đồng cũng như trong lớp dẫn xuất.


0

Các bộ tốt nhất bên trong được bảo vệ khi bạn muốn một thành viên hoặc loại được sử dụng trong một lớp dẫn xuất từ ​​một hội đồng khác đồng thời chỉ muốn tiêu thụ thành viên hoặc gõ vào tập hợp cha mà không xuất phát từ lớp được khai báo. Ngoài ra nếu bạn chỉ muốn sử dụng một thành viên hoặc loại mà không xuất phát từ một lớp khác, trong cùng một hội đồng, bạn chỉ có thể sử dụng nội bộ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.