【问题标题】:What are the default access modifiers in C#?C# 中的默认访问修饰符是什么?
【发布时间】:2011-02-01 01:30:49
【问题描述】:

类、方法、成员、构造函数、委托和接口的默认访问修饰符是什么?

【问题讨论】:

    标签: c# access-modifiers


    【解决方案1】:

    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 节):

    取决于上下文 成员声明发生,只有 某些类型的声明 可访问性是允许的。 此外,当成员声明 不包括任何访问修饰符, 声明的上下文 发生确定默认 声明的可访问性。

    • 命名空间隐含地具有公开声明的可访问性。无法访问 命名空间上允许使用修饰符 声明。
    • 在编译单元或命名空间中声明的类型可以具有公共或 内部声明的可访问性和 默认为内部声明 可访问性。
    • 类成员可以具有五种声明的可访问性中的任何一种 并默认为私有声明 可访问性。 (注意一个类型 声明为类的成员可以 有五种声明中的任何一种 可访问性,而声明的类型 作为命名空间的成员可以有 仅公开或内部声明 可访问性。)
    • 结构成员可以声明公共、内部或私有 可访问性和默认为私有 声明可访问性,因为结构 被隐式密封。结构成员 在结构中引入(也就是说,不是 由该结构继承)不能有 受保护或受保护的内部 声明的可访问性。 (请注意,一个 声明为结构成员的类型 可以有公共的、内部的或私有的 声明的可访问性,而类型 声明为命名空间的成员 只能有公共或内部 声明的可访问性。)
    • 接口成员隐含地具有公开声明的可访问性。不 允许访问修饰符 接口成员声明。
    • 枚举成员隐含地具有公开声明的可访问性。不 允许访问修饰符 枚举成员声明。

    (请注意,嵌套类型将位于“类成员”或“结构成员”部分之下 - 因此默认为私有可见性。)

    【讨论】:

    • 注意:在 C# 8 中,接口中允许访问修饰符,默认为 public。
    【解决方案2】:
    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!
    

    【讨论】:

    • 这并不清楚如果一个类也是一个成员(由于是嵌套类型),那么它默认为私有。此外,接口和枚举的成员始终是公开的。
    • @niry 不,它不是私人的。它是公开的。它只是没有在实现类型中获得一个槽,所以如果class Foo : IFoo { IFoo.M() {} } ... Foo a = new Foo();,你不能用a.M() 访问M,但是你可以用(a as IFoo).M() 访问它。 (查看规范以获取有关细节的更多信息)
    • 由于我们没有为接口方法指定任何访问修饰符,它们总是公开的。
    【解决方案3】:

    简短回答: 最小可能访问权限(参见 Jon Skeet 的回答)。

    长答案:

    非嵌套类型、枚举和委托可访问性可能只有内部或公共可访问性

                         | Default   | Permitted declared accessibilities
    ------------------------------------------------------------------
    namespace            | public    | none (always implicitly public)
    
    enum                 | public    | public, internal
    
    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    | All¹
    
    interface            | public    | All¹
    
    class                | private   | All¹
    
    struct               | private   | public, internal, private²
    
    delegate             | private   | All¹
    
    constructor          | private   | All¹
    
    enum member          | public    | none (always implicitly public)
    
    interface member     | public    | none (always implicitly public)
         
    method               | private   | All¹
    
    field                | private   | All¹
    
    user-defined operator| none      | public (must be declared public)
    

    ¹ 全部 === 公开的、受保护的、内部的、私有的、受保护的内部

    ² 结构不能从结构或类继承(尽管它们可以,接口),因此 protected 不是有效的修饰符

    嵌套类型的可访问性取决于其可访问域,该域由成员声明的可访问性和直接包含类型的可访问域共同决定。但是,嵌套类型的可访问域不能超过包含类型的可访问域。

    注意:CIL 还提供了protected 和 internal(与现有的 protected “或” internal 相对),但据我所知,这目前不适用于 C#。 p>


    见:

    http://msdn.microsoft.com/en-us/library/ba0a1yw2.aspx
    http://msdn.microsoft.com/en-us/library/ms173121.aspx
    http://msdn.microsoft.com/en-us/library/cx03xt0t.aspx
    (我喜欢微软的 URL……)

    【讨论】:

    • 这个答案部分不正确。非嵌套枚举也可以是内部的。嵌套的枚举和接口可以是从公共到私有的任何东西。
    • 如果您对自己的理解有信心,请随时进行编辑。我不再了解 C#...
    【解决方案4】:

    看看Access Modifiers (C# Programming Guide)

    类和结构可访问性

    在命名空间中直接声明的类和结构(换句话说,不嵌套在其他类或结构中)可以是公共的或内部的。如果未指定访问修饰符,则默认为 Internal。

    结构成员,包括嵌套类和结构,可以声明为公共、内部或私有。类成员,包括嵌套类和结构,可以是公共的、受保护的内部的、受保护的、内部的、私有的、受保护的或私有的。默认情况下,类成员和结构成员(包括嵌套类和结构)的访问级别是私有的。私有嵌套类型不能从包含类型的外部访问。

    派生类的可访问性不能高于其基类。换句话说,你不能有一个从内部类 A 派生的公共类 B。如果允许这样做,它将具有使 A 成为公共的效果,因为 A 的所有受保护或内部成员都可以从派生类访问。

    您可以使用InternalsVisibleToAttribute 启用特定的其他程序集来访问您的内部类型。有关详细信息,请参阅朋友大会。

    类和结构成员可访问性

    类成员(包括嵌套类和结构)可以用六种访问类型中的任何一种来声明。结构成员不能声明为受保护的,因为结构不支持继承。

    通常,成员的可访问性不大于包含它的类型的可访问性。但是,如果内部类的公共成员实现接口方法或覆盖公共基类中定义的虚拟方法,则该成员可能可以从程序集外部访问。

    作为字段、属性或事件的任何成员的类型必须至少与成员本身一样可访问。同样,作为方法、索引器或委托的任何成员的返回类型和参数类型必须至少与成员本身一样可访问。例如,您不能有一个返回类 C 的公共方法 M,除非 C 也是公共的。同样,如果 A 被声明为私有,则不能拥有 A 类型的受保护属性。

    用户定义的运算符必须始终声明为 public 和 static。有关详细信息,请参阅运算符重载。

    终结器不能有可访问性修饰符。

    其他类型

    直接在命名空间中声明的接口可以声明为公共的或内部的,就像类和结构一样,接口默认为内部访问。接口成员始终是公共的,因为接口的目的是使其他类型能够访问类或结构。不能对接口成员应用访问修饰符。

    枚举成员始终是公共的,不能应用访问修饰符。

    委托的行为类似于类和结构。默认情况下,直接在命名空间中声明时它们具有内部访问权限,而嵌套时则具有私有访问权限。

    【讨论】:

      【解决方案5】:

      类默认为内部

      • 默认情况下,类成员是私有的

      接口默认为内部

      • 接口成员默认为public。 (接口不允许 我们可以指定对其成员的任何类型的可访问性。)

        注意:如果你尝试为接口的成员指定任何访问说明符,则会显示编译错误。

      结构默认为内部

      • 结构成员默认为私有

      【讨论】:

        【解决方案6】:

        我想添加一些文档链接。查看更多详细信息here

        【讨论】:

        • 类默认是内部的而不是私有的。
        • 我写的课程是私人的?
        • 此表仅对嵌套类型有效。
        • 类默认是内部的,命名空间内的类不能是私有的。但是类中的类(嵌套类)可以是私有的
        • 接口的访问修饰符默认为Internal
        【解决方案7】:

        最简单的答案如下.....

        默认情况下,C# 中的所有成员始终采用 LEAST 可访问修饰符。

        这就是为什么程序集中的所有顶级类默认情况下都是“内部”的,这意味着它们对所在的程序集是公共的,但对外部程序集是私有的或被排除在外。顶级课程的唯一其他选择是更易于访问的公共。对于嵌套类型,它都是私有的,除了一些罕见的例外,比如只能是公共的枚举成员和接口。一些例子。对于顶级类和接口,默认值为:

        class Animalinternal class Animal

        相同

        接口动物公共接口动物

        相同

        对于嵌套类和接口(内部类型),默认值为:

        class Animalprivate class Animal

        相同

        接口Animal私有接口Animal

        相同

        如果您只是假设默认值始终是最私密的,那么您不需要使用访问器,直到您需要更改默认值。很简单。

        【讨论】:

          【解决方案8】:

          命名空间级别:internal

          类型级别:private

          【讨论】:

          • 正确答案,但没有参考权威source,必须盲目信任。
          【解决方案9】:

          内部是默认修饰符

          【讨论】:

          • 不适用于班级成员
          猜你喜欢
          • 2011-04-10
          • 2013-04-16
          • 1970-01-01
          • 2014-04-01
          • 1970-01-01
          • 2021-06-10
          • 2012-03-03
          相关资源
          最近更新 更多