ความแตกต่างระหว่าง 'ที่ได้รับการป้องกัน' และ 'การป้องกันภายใน' คืออะไร


244

ใครสามารถช่วยอธิบายความแตกต่างระหว่างตัวดัดแปลง 'ที่ได้รับการป้องกัน' และ 'ที่ได้รับการป้องกันภายใน' ใน C # ได้หรือไม่? ดูเหมือนว่าพวกเขาจะทำงานในลักษณะเดียวกัน

คำตอบ:


402

โมดิฟายเออร์สำหรับการเข้าถึง "ที่ได้รับการป้องกันภายใน" คือการรวมกันของทั้ง "การป้องกัน" และ "ภายใน"

จากMSDN, ตัวดัดแปลงการเข้าถึง (คู่มือการเขียนโปรแกรม C #) :

ป้องกัน :

ประเภทหรือสมาชิกสามารถเข้าถึงได้โดยรหัสในคลาสหรือโครงสร้างเดียวกันหรือในคลาสที่ได้รับมาจากคลาสนั้น

ภายใน :

ประเภทหรือสมาชิกสามารถเข้าถึงได้โดยรหัสใด ๆ ในการชุมนุมเดียวกัน แต่ไม่ได้มาจากการชุมนุมอื่น

ป้องกันภายใน :

ประเภทหรือสมาชิกสามารถเข้าถึงได้โดยรหัสใด ๆ ในการชุมนุมที่มีการประกาศหรือจากภายในชั้นเรียนที่ได้รับในการชุมนุมอื่น การเข้าถึงจากแอสเซมบลีอื่นต้องเกิดขึ้นภายในการประกาศคลาสที่มาจากคลาสที่มีการประกาศองค์ประกอบภายในที่ได้รับการป้องกันและจะต้องดำเนินการผ่านอินสแตนซ์ของประเภทคลาสที่ได้รับ

โปรดทราบว่า : protected internalหมายถึง " protectedหรือinternal" (คลาสใด ๆ ในแอสเซมบลีเดียวกันหรือคลาสที่ได้รับ - แม้ว่าจะอยู่ในแอสเซมบลีที่แตกต่างกัน)

... และเพื่อความสมบูรณ์:

ส่วนตัว :

ประเภทหรือสมาชิกสามารถเข้าถึงได้โดยรหัสในชั้นเรียนหรือโครงสร้างเดียวกัน

สาธารณะ :

ประเภทหรือสมาชิกสามารถเข้าถึงได้โดยรหัสอื่นใดในการชุมนุมเดียวกันหรือการชุมนุมอื่นที่อ้างอิงมัน

ป้องกันส่วนตัว :

การเข้าถึงถูก จำกัด ไปยังคลาสที่ประกอบด้วยหรือชนิดที่ได้รับมาจากคลาสที่ประกอบด้วยภายในแอสเซมบลีปัจจุบัน
( มีให้ตั้งแต่ C # 7.2 )


2
ฉันสามารถมีสมาชิกprotected internalเพื่อให้มันprotectedอยู่ในการชุมนุมในปัจจุบันและไม่สามารถใช้งานได้อย่างสมบูรณ์จากภายนอก?
Shimmy Weitzhandler

8
นั่นจะเป็น "ป้องกัน" ใช่ไหม?
CAD bloke

2
@Shimmy: คุณสามารถมีภายในชั้นเรียนกับการป้องกันวิธีการ แต่จากนั้นทั้งคลาสจะไม่พร้อมใช้งานจากชุดประกอบภายนอก
M4N

1
@Shimmy ลองดูที่ข้อเสนอนี้เพื่อหา C # github.com/dotnet/roslyn/blob/features/privateProtected/docs/…
Nate Cook

@Shimmy อย่างน้อย CLR สนับสนุนแนวคิดของจุดตัดของการป้องกันและการเข้าถึงภายใน แต่ภาษา C # ไม่ได้ C # รองรับการรวมกันของตัวดัดแปลงการเข้าถึงสองตัวเท่านั้น
RBT

89

protected สามารถใช้คลาสย่อยใดก็ได้จากชุดประกอบใด ๆ

protected internalคือทุกอย่างที่protectedเป็นบวกกับทุกสิ่งในแอสเซมบลีเดียวกันสามารถเข้าถึงได้

ที่สำคัญไม่ได้หมายถึง "คลาสย่อยในแอสเซมบลีเดียวกัน" - มันคือการรวมกันของทั้งสองไม่ใช่การแยก


3
เพียงแค่ FYI สำหรับผู้อ่านที่ CLR สนับสนุนแนวคิดของจุดตัดของการป้องกันและการเข้าถึงภายในเช่นกัน แต่ C # ไม่รองรับสิ่งนี้ C # รองรับเฉพาะสหภาพของทั้งสองตามที่กล่าวไว้ในโพสต์นี้
RBT

1
FYI อีกตัวหนึ่งสำหรับผู้อ่าน "subclasses ในแอสเซมบลีเดียวกัน" สามารถทำได้ด้วยprivate protectedตัวปรับการเข้าถึงที่เปิดตัวใน C # 7.2
LordWilmore

52

- อัปเดตคำตอบ 2019 -

คุณสามารถค้นหาความแตกต่างในการเข้าถึงตามตารางด้านล่างคือใช่

ป้อนคำอธิบายรูปภาพที่นี่


4
คำตอบที่สวยงามมันสื่อสารอย่างชัดเจนถึงความแตกต่างระหว่างตัวดัดแปลงการเข้าถึงแต่ละตัว
e_i_pi

23

ในทางปฏิบัติเกี่ยวกับวิธีการ:

ได้รับการป้องกัน - เข้าถึงได้สำหรับคลาสที่สืบทอดมาหรือเป็นส่วนตัว

ภายใน - สาธารณะสำหรับคลาสภายในแอสเซมบลีส่วนตัวเท่านั้น

ป้องกันภายใน - หมายถึงการป้องกันหรือภายใน - วิธีการที่สามารถเข้าถึงได้สำหรับชั้นเรียนที่สืบทอดและสำหรับชั้นเรียนใด ๆ ภายในการชุมนุม


1
ฉันจะใช้ OR เพื่อแสดงว่ามันไม่ใช่ทั้งสองอย่างที่เป็นจริง
Brian Rasmussen

ฉันไม่เห็นด้วยอย่างสมบูรณ์กับส่วน "สำหรับการเปลี่ยนพฤติกรรมคลาสพื้นฐาน" ในคำอธิบายของ "การป้องกัน" ฉันจะบอกว่านี่เป็นที่ที่คุณใช้ "virtual" (บนคลาสพื้นฐาน) และ "override" (บนคลาสที่ได้รับ)
M4N

มีวิธีการทำเครื่องหมายสมาชิกว่าเป็นprotectedAND internalหรือไม่?
Shimmy Weitzhandler

@Shimmy: protected internalใช่
abatishchev

1
@ ชิมมี่อีกสองปีต่อมาและใช่ ตอนนี้มีวิธีใน C # 7.2 มันเรียกว่าprivate protected docs.microsoft.com/en-us/dotnet/csharp/language-reference/ …
Pauli Østerø

10

ยังคงมีความสับสนมากมายในการทำความเข้าใจขอบเขตของ accessors "ป้องกันภายใน" แต่ส่วนใหญ่มีคำจำกัดความที่กำหนดไว้อย่างถูกต้อง สิ่งนี้ช่วยให้ฉันเข้าใจความสับสนระหว่าง "การป้องกัน" และ "การป้องกันภายใน":

สาธารณะเป็นสาธารณะจริงๆทั้งภายในและภายนอกการชุมนุม ( สาธารณะภายใน / สาธารณะภายนอก )

การป้องกันได้รับการคุ้มครองอย่างแท้จริงทั้งภายในและภายนอกการชุมนุม ( การป้องกันภายใน / การป้องกันภายนอก ) (ไม่อนุญาตในคลาสระดับบนสุด)

ส่วนตัวเป็นส่วนตัวทั้งภายในและภายนอกการชุมนุม ( ส่วนตัวภายใน / ส่วนตัวภายนอก ) (ไม่อนุญาตในชั้นเรียนระดับบนสุด)

ภายในเป็นสาธารณะจริงๆภายในแอสเซมบลี แต่แยกออกนอกแอสเซมบลีเช่นส่วนตัว ( สาธารณะภายใน / ภายนอกที่ยกเว้น )

ได้รับการคุ้มครองภายในเป็นสาธารณะจริงๆภายในแอสเซมบลี แต่ป้องกันนอกแอสเซมบลี ( สาธารณะภายใน / ภายนอกป้องกัน ) (ไม่อนุญาตในคลาสระดับบนสุด)

ในขณะที่คุณสามารถดูการป้องกันภายในเป็นสัตว์ที่แปลกมาก ไม่เข้าใจง่าย

นั่นทำให้เกิดคำถามว่าทำไม Microsoft ไม่สร้าง ( ป้องกันภายใน / ยกเว้นจากภายนอก ) หรือฉันเดาว่า "การป้องกันส่วนตัว" หรือ "การป้องกันภายใน" บางประเภท? ฮ่า ๆ. ดูเหมือนว่าไม่สมบูรณ์หรือ

ความสับสนที่เพิ่มเข้ามาคือความจริงที่ว่าคุณสามารถซ้อนข้อมูลสมาชิกแบบซ้อนภายในหรือแบบสาธารณะที่มีการป้องกันแบบภายในหรือแบบส่วนตัว เหตุใดคุณจึงเข้าถึง "ที่ได้รับการป้องกันภายใน" ที่ซ้อนอยู่ภายในคลาสภายในที่ไม่รวมการเข้าถึงจากภายนอก

Microsoft กล่าวว่าประเภทที่ซ้อนกันนั้นถูก จำกัด โดยขอบเขตประเภทพาเรนต์ แต่นั่นไม่ใช่สิ่งที่คอมไพเลอร์พูด คุณสามารถรวบรวม internals ที่ได้รับการป้องกันภายในคลาสภายในซึ่งควร จำกัด ขอบเขตให้กับแอสเซมบลีเท่านั้น

สำหรับฉันแล้วรู้สึกเหมือนการออกแบบที่ไม่สมบูรณ์ ควรมีขอบเขตที่ง่ายขึ้นสำหรับทุกประเภทในระบบที่พิจารณาการสืบทอดอย่างชัดเจน แต่ยังรวมถึงความปลอดภัยและลำดับชั้นของชนิดที่ซ้อนกัน สิ่งนี้จะทำให้การแบ่งปันวัตถุเป็นไปอย่างง่ายดายและเป็นธรรมชาติมากกว่าการค้นหาการเข้าถึงประเภทและสมาชิกบนพื้นฐานของระบบการกำหนดขอบเขตที่ไม่สมบูรณ์


1
การป้องกันแบบส่วนตัวได้รับการเพิ่มใน C # 7.2 ซึ่งโดยพื้นฐานแล้วเป็นแบบภายในและได้รับการป้องกัน
Pauli Østerø

7

ได้รับการป้องกัน : ตัวแปรหรือวิธีการจะใช้ได้เฉพาะกับคลาสลูก (ในชุดประกอบใด ๆ )

ได้รับการป้องกันภายใน : ใช้ได้กับคลาสเด็กในแอสเซมบลีใด ๆและทุกคลาสภายในแอสเซมบลีเดียวกัน


3

ฉันอ่านคำจำกัดความที่ชัดเจนสำหรับคำเหล่านี้แล้ว

ได้รับการป้องกัน: การเข้าถึงถูก จำกัด ภายในนิยามคลาสและคลาสใด ๆ ที่สืบทอดจากคลาส ประเภทหรือสมาชิกสามารถเข้าถึงได้โดยรหัสในคลาสหรือโครงสร้างเดียวกันหรือในคลาสที่ได้รับมาจากคลาสนั้น

ภายใน: การเข้าถึง จำกัด เฉพาะคลาสที่กำหนดภายในแอสเซมบลีโครงการปัจจุบันเท่านั้น ประเภทหรือสมาชิกสามารถเข้าถึงได้โดยรหัสในชั้นเรียนเดียวกัน

ได้รับการคุ้มครอง - ภายใน: การเข้าถึงถูก จำกัด เฉพาะแอสเซมบลีปัจจุบันหรือชนิดที่ได้มาจากคลาสที่ประกอบด้วย


1

สมาชิกที่ได้รับการคุ้มครอง

สมาชิกที่ได้รับการปกป้องของชั้นเรียนจะมีให้เฉพาะในชั้นเรียนที่มีอยู่ (ซึ่งมีการประกาศ) และในชั้นเรียนที่ได้รับภายในการชุมนุมและนอกการชุมนุม

หมายถึงถ้าคลาสที่อยู่นอกแอสเซมบลีสามารถใช้สมาชิกที่มีการป้องกันของแอสเซมบลีอื่นโดยสืบทอดคลาสนั้นเท่านั้น

เราสามารถเปิดเผยสมาชิกที่ได้รับการป้องกันนอกการชุมนุมโดยรับคลาสนั้นและใช้ในคลาสที่ได้รับเท่านั้น

หมายเหตุ: สมาชิกที่ได้รับการป้องกันจะไม่สามารถเข้าถึงได้โดยใช้วัตถุในคลาสที่ได้รับ

สมาชิกภายใน

สมาชิกภายในของคลาสนั้นพร้อมใช้งานหรือการเข้าถึงภายในแอสเซมบลีไม่ว่าจะเป็นการสร้างวัตถุหรือในคลาสที่ได้รับมาหรือคุณสามารถพูดว่ามันสามารถเข้าถึงได้ในทุกคลาสภายในแอสเซมบลี

หมายเหตุ: สมาชิกภายในไม่สามารถเข้าถึงได้ภายนอกแอสเซมบลีโดยใช้การสร้างวัตถุหรือในคลาสที่ได้รับ

ป้องกันภายใน

Protifier Internal access Protected เป็นการรวมกันแบบ Protected หรือ Internal

สมาชิกภายในที่ได้รับความคุ้มครองสามารถใช้งานได้ภายในแอสเซมบลีทั้งหมดที่ได้ประกาศว่าจะสร้างวัตถุหรือโดยการสืบทอดคลาสนั้น และสามารถเข้าถึงได้นอกการชุมนุมในชั้นเรียนที่ได้รับเท่านั้น

หมายเหตุ: สมาชิกภายในที่ได้รับการป้องกันจะทำงานเป็นภายในภายในแอสเซมบลีเดียวกันและทำงานเหมือนกับที่ได้รับการป้องกันสำหรับแอสเซมบลีภายนอก


1

สาธารณะ - สมาชิก (ฟังก์ชั่นและตัวแปร) ประกาศเป็นสาธารณะสามารถเข้าถึงได้จากทุกที่

ส่วนตัว - สมาชิกส่วนตัวไม่สามารถเข้าถึงได้จากนอกชั้นเรียน นี่คือตัวระบุการเข้าถึงเริ่มต้นสำหรับสมาชิกเช่นหากคุณไม่ได้ระบุตัวระบุการเข้าถึงสำหรับสมาชิก (ตัวแปรหรือฟังก์ชั่น) มันจะถือว่าเป็นส่วนตัว ดังนั้นสตริง PhoneNumber; เทียบเท่ากับสตริงส่วนตัว PhoneNumber

การป้องกัน - สมาชิกที่ได้รับความคุ้มครองสามารถเข้าถึงได้จากคลาสลูกเท่านั้น

ภายใน - สามารถเข้าถึงได้ภายในแอสเซมบลีเดียวกันเท่านั้น

ได้รับการป้องกันภายใน - สามารถเข้าถึงได้ภายในแอสเซมบลีเดียวกันและในคลาสที่ได้รับ


0

ป้องกันชุดที่ดีที่สุดภายในเมื่อคุณต้องการให้สมาชิกหรือประเภทที่จะใช้ในชั้นเรียนที่ได้รับจากการชุมนุมอื่นในเวลาเดียวกันเพียงแค่ต้องการที่จะใช้สมาชิกหรือประเภทในการประกอบหลักโดยไม่ได้รับมาจากชั้นที่มีการประกาศ นอกจากนี้หากคุณต้องการใช้สมาชิกหรือประเภทที่ไม่ได้มาจากคลาสอื่นในแอสเซมบลีเดียวกันคุณสามารถใช้ภายในเท่านั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.