ตัวดัดแปลงการเข้าถึงเริ่มต้นใน C # คืออะไร


383

ตัวดัดแปลงการเข้าถึงเริ่มต้นสำหรับคลาสวิธีการสมาชิกตัวสร้างผู้รับมอบสิทธิ์และอินเทอร์เฟซคืออะไร

คำตอบ:


485

การเข้าถึงเริ่มต้นสำหรับทุกอย่างใน C # คือ"การเข้าถึง จำกัด มากที่สุดที่คุณสามารถประกาศของสมาชิกว่า"

ตัวอย่างเช่น:

namespace MyCompany
{
    class Outer
    {
        void Foo() {}
        class Inner {}
    }
}

เทียบเท่ากับ

namespace MyCompany
{
    internal class Outer
    {
        private void Foo() {}
        private class Inner {}
    }
}

ข้อยกเว้นหนึ่งข้อในการทำเช่นนี้คือการทำให้ส่วนหนึ่งของพร็อพเพอร์ตี้ (โดยปกติคือ setter) ถูก จำกัด มากกว่าความสามารถในการเข้าถึงของคุณสมบัติที่ประกาศไว้:

public string Name
{
    get { ... }
    private set { ... } // This isn't the default, have to do it explicitly
}

นี่คือความหมายของข้อกำหนด C # 3.0 (ส่วน 3.5.1):

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

  • namespaces โดยปริยายมีการประกาศการเข้าถึงสาธารณะ ไม่อนุญาตการปรับเปลี่ยนการเข้าถึงในการประกาศเนมสเปซ
  • ประเภทที่ประกาศในหน่วยการรวบรวมหรือเนมสเปซสามารถมีความสามารถในการเข้าถึงสาธารณะหรือภายในที่ประกาศไว้
  • สมาชิกของคลาสสามารถมีการเข้าถึงที่ประกาศไว้ห้าประเภทและเป็นค่าเริ่มต้นสำหรับการเข้าถึงแบบส่วนตัวที่ประกาศไว้ (โปรดทราบว่าประเภทที่ประกาศเป็นสมาชิกของคลาสสามารถมีความสามารถในการเข้าถึงที่ประกาศไว้ห้าชนิดในขณะที่ประเภทที่ประกาศเป็นสมาชิกของเนมสเปซสามารถเข้าถึงได้เฉพาะการประกาศสาธารณะหรือภายในเท่านั้น)
  • สมาชิกโครงสร้างสามารถมีการเข้าถึงสาธารณะประกาศภายในหรือส่วนตัวประกาศและเริ่มต้นการเข้าถึงประกาศส่วนตัวเพราะ struct ถูกปิดผนึกโดยปริยาย สมาชิกโครงสร้างที่แนะนำในโครงสร้าง (นั่นคือไม่สืบทอดโดยโครงสร้างนั้น) ไม่สามารถป้องกันหรือป้องกันการเข้าถึงที่ประกาศภายใน (โปรดทราบว่าประเภทที่ประกาศเป็นสมาชิกของโครงสร้างสามารถมีการเข้าถึงสาธารณะประกาศภายในหรือส่วนตัวประกาศในขณะที่ประเภทประกาศเป็นสมาชิกของ namespace สามารถเข้าถึงได้เฉพาะสาธารณะหรือภายในประกาศ)
  • สมาชิกอินเทอร์เฟซโดยนัยมีการประกาศการเข้าถึงสาธารณะ ไม่อนุญาตการปรับเปลี่ยนการเข้าถึงในการประกาศสมาชิกอินเตอร์เฟส
  • การแจงนับสมาชิกโดยปริยายมีการประกาศการเข้าถึงสาธารณะ ไม่อนุญาตให้ผู้ดัดแปลงเข้าถึงการประกาศการแจงนับสมาชิก

(โปรดทราบว่าประเภทที่ซ้อนกันจะอยู่ภายใต้ส่วน "สมาชิกคลาส" หรือ "สมาชิกโครงสร้าง" - และดังนั้นจึงเป็นค่าเริ่มต้นการมองเห็นส่วนตัว)


154
top level class: internal
method: private
members (unless an interface or enum): private (including nested classes)
members (of interface or enum): public
constructor: private (note that if no constructor is explicitly defined, a public default constructor will be automatically defined)
delegate: internal
interface: internal
explicitly implemented interface member: public!

13
สิ่งนี้ไม่ทำให้ชัดเจนว่าถ้าคลาสนั้นเป็นสมาชิกด้วย (เนื่องจากเป็นชนิดซ้อนกัน) ก็จะมีค่าเริ่มต้นเป็นส่วนตัว นอกจากนี้สมาชิกของอินเทอร์เฟซและ enum มักเป็นสาธารณะ
Jon Skeet

1
@niry ไม่มันไม่ใช่แบบส่วนตัว เป็นสาธารณะ มันก็ไม่ได้รับสล็อตในรูปแบบการดำเนินการดังนั้นหากclass Foo : IFoo { IFoo.M() {} } ... Foo a = new Foo();คุณไม่สามารถเข้าถึงได้Mด้วยแต่คุณสามารถเข้าถึงได้ด้วยa.M() (a as IFoo).M()(ตรวจสอบข้อมูลจำเพาะสำหรับข้อมูลเพิ่มเติมเกี่ยวกับข้อมูลเฉพาะ)
M.Stramm

130

คำตอบสั้น ๆ :เข้าถึงได้น้อยที่สุด (คำตอบของ Jon Skeet)

คำตอบยาว:

ประเภทที่ไม่ซ้อนกันการแจงนับและความสามารถในการเข้าถึงของผู้รับมอบสิทธิ์ (อาจมีความสามารถในการเข้าถึงภายในหรือสาธารณะเท่านั้น )

                     | Default   | Permitted declared accessibilities
------------------------------------------------------------------
namespace            | public    | none (always implicitly public)

enum                 | public    | none (always implicitly public)

interface            | internal  | public, internal

class                | internal  | public, internal

struct               | internal  | public, internal

delegate             | internal  | public, internal

ประเภทซ้อนและการเข้าถึงของสมาชิก

                     | Default   | Permitted declared accessibilities
------------------------------------------------------------------
namespace            | public    | none (always implicitly public)

enum                 | public    | none (always implicitly public)

interface            | public    | none

class                | private   | All¹

struct               | private   | public, internal, private²

delegate             | private   | All¹

constructor          | private   | All¹

interface member     | public    | none (always implicitly public)

method               | private   | All¹

field                | private   | All¹

user-defined operator| none      | public (must be declared public)

¹ทั้งหมด === สาธารณะได้รับการป้องกันภายในส่วนตัวและได้รับการป้องกันภายใน

² structs ไม่สามารถสืบทอดจาก structs หรือคลาส (แม้ว่าจะสามารถ, อินเตอร์เฟส), ดังนั้นการป้องกันจึงไม่ใช่ตัวดัดแปลงที่ถูกต้อง

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

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


ดู:

http://msdn.microsoft.com/en-us/library/ba0a1yw2.aspx
http://msdn.microsoft.com/en-us/library/ms173121.aspx
http://msdn.microsoft.com/en- เรา / library / cx03xt0t.aspx
(ผู้ชายฉันรัก Microsoft URIs ... )


12

ดูที่Access Modifiers (คู่มือการเขียนโปรแกรม C #)

การเข้าถึงคลาสและโครงสร้าง

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

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

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

คุณสามารถเปิดใช้ประกอบอื่น ๆ InternalsVisibleToAttributeที่เฉพาะเจาะจงในการเข้าถึงประเภทภายในของคุณโดยใช้ สำหรับข้อมูลเพิ่มเติมดูชุดประกอบเพื่อน

การเข้าถึงสมาชิกระดับและโครงสร้าง

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

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

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

ตัวดำเนินการที่ผู้ใช้กำหนดต้องประกาศเป็นสาธารณะและคงที่เสมอ สำหรับข้อมูลเพิ่มเติมดูตัวดำเนินการมากไป

Finalizers ไม่สามารถปรับเปลี่ยนการเข้าถึงได้

ประเภทอื่น ๆ

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

สมาชิกการแจงนับเป็นสาธารณะอยู่เสมอและไม่สามารถใช้ตัวดัดแปลงการเข้าถึงได้

ผู้รับมอบสิทธิ์ประพฤติเช่นคลาสและ structs โดยค่าเริ่มต้นพวกเขามีการเข้าถึงภายในเมื่อประกาศโดยตรงภายในเนมสเปซและการเข้าถึงส่วนตัวเมื่อซ้อนกัน


8

ชั้นภายในโดยค่าเริ่มต้น

  • สมาชิกของคลาสจะเป็นส่วนตัวโดยค่าเริ่มต้น

อินเตอร์เฟซที่เป็นภายในโดยค่าเริ่มต้น

  • สมาชิกส่วนต่อประสานจะเป็นแบบสาธารณะโดยค่าเริ่มต้น (อินเทอร์เฟซจะไม่อนุญาตให้เราระบุการเข้าถึงใด ๆ กับสมาชิก)

    หมายเหตุ:หากคุณพยายามระบุตัวระบุการเข้าถึงใด ๆ ให้กับสมาชิกของอินเตอร์เฟสมันจะแสดงข้อผิดพลาดในการคอมไพล์

โครงสร้างเป็นภายในโดยค่าเริ่มต้น

  • สมาชิกโครงสร้างเป็นส่วนตัวโดยค่าเริ่มต้น

5

ฉันต้องการที่จะเพิ่มลิงค์เอกสารบางอย่าง ตรวจสอบรายละเอียดเพิ่มเติมที่นี่

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


1
คลาสเป็นค่าเริ่มต้นภายในและไม่เป็นส่วนตัว
Baahubali

1
ฉันเขียนคลาสส่วนตัวที่ไหน?
Asif Mushtaq

ตารางนี้ใช้ได้สำหรับประเภทซ้อนกันเท่านั้น
BlueSilver

class เป็นค่าเริ่มต้นภายในและคลาสภายใน namespace ไม่สามารถเป็นแบบส่วนตัวได้ แต่คลาสภายในคลาส (คลาสซ้อนกัน) สามารถเป็นส่วนตัวได้
อรุณ

ปรับปรุงการเข้าถึงอินเตอร์เฟซที่เป็นภายในโดยค่าเริ่มต้น
Kamala Hanchinal

4

คำตอบที่ง่ายที่สุดคือต่อไปนี้ .....

สมาชิกทั้งหมดใน C # จะต้องใช้ตัวแก้ไขการเข้าถึงที่เป็นไปได้ของ LEAST โดยค่าเริ่มต้นเสมอ

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

ชั้นสัตว์เช่นเดียวกับสัตว์ชั้นภายใน

อินเตอร์เฟซสัตว์เช่นเดียวกับสัตว์อินเตอร์เฟซสาธารณะ

ในกรณีของคลาสที่ซ้อนกันและอินเทอร์เฟซ (ชนิดภายใน) ค่าเริ่มต้นคือ:

ชั้นสัตว์เช่นเดียวกับสัตว์ชั้นส่วนตัว

สัตว์เช่นเดียวกับสัตว์อินเตอร์เฟซส่วนตัว

หากคุณเพียงแค่สมมติว่าค่าเริ่มต้นนั้นเป็นค่าส่วนตัวที่สุดเสมอคุณไม่จำเป็นต้องใช้อุปกรณ์เสริมจนกว่าคุณจะต้องเปลี่ยนค่าเริ่มต้น ง่าย.



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