在C#中,public,private,protected和没有访问修饰符有什么区别?

时间:2009-03-05 13:48:38

标签: c# .net asp.net access-modifiers

我所有大学时期都在使用public,想知道publicprivateprotected之间的区别吗?

static做什么而不是什么?

17 个答案:

答案 0 :(得分:955)

访问修饰符

  

来自docs.microsoft.com

     

公开

     
    

类型或成员可以由同一程序集中的任何其他代码或引用它的另一个程序集访问。

  
     

<强>私有

     
    

只能通过同一类或结构中的代码访问类型或成员。

  
     

<强>保护

     
    

只能通过相同类或结构中的代码或派生类访问类型或成员。

  
     

私有保护(在C#7.2中添加)

     
    

类型或成员只能通过相同类或结构中的代码访问,或者可以通过同一程序集中的派生类访问,但不能通过其他程序集访问。

  
     

<强>内部

     
    

类型或成员可以由同一程序集中的任何代码访问,但不能从其他程序集访问。

  
     

受保护的内部

     
    

类型或成员可以由同一程序集中的任何代码访问,也可以由另一个程序集中的任何派生类访问。

  

设置无访问修饰符时,将使用默认访问修饰符。因此,即使没有设置,也总会有某种形式的访问修饰符。

<强>静态

  

类上的static修饰符意味着该类无法实例化,并且其所有成员都是静态的。静态成员有一个版本,无论其封闭类型的实例数是多少。

     

静态类与非静态类基本相同,但有一个区别:静态类不能在外部实例化。换句话说,您不能使用new关键字来创建类类型的变量。因为没有实例变量,所以可以使用类名本身来访问静态类的成员。

     

然而,有static constructor这样的事情。任何类都可以包含其中一个,包括静态类。它们不能直接调用&amp;不能有参数(除了类本身的任何类型参数)。在创建第一个实例或引用任何静态成员之前,会自动调用静态构造函数来初始化类。看起来像这样:

static class Foo()
{
    static Foo()
    {
        Bar = "fubar";
    }

    public static string Bar { get; set; }
}

静态类通常用作服务,您可以像这样使用它们:

MyStaticClass.ServiceMethod(...);

答案 1 :(得分:154)

公开 - 如果您可以看到该课程,那么您可以看到方法

私有 - 如果您该类的一部分,那么您可以看到该方法,否则不会。

受保护 - 与私有相同,加上所有后代也可以看到该方法。

静态(类) - 还记得“Class”和“Object”之间的区别吗?忘记这一切。它们与“静态”相同......类是它自己的唯一实例。

静态(方法) - 每当使用此方法时,它将具有独立于其所属类的实际实例的引用框架。

答案 2 :(得分:144)

图形概述(简要总结)

Visibility

如果您没有在前面放置访问修饰符,则默认设置,请参见此处:
Default visibility for C# classes and members (fields, methods, etc)?

非嵌套

enum                              public
non-nested classes / structs      internal
interfaces                        internal
delegates in namespace            internal
class/struct member(s)            private
delegates nested in class/struct  private

嵌套:

nested enum      public
nested interface public
nested class     private
nested struct    private

答案 3 :(得分:22)

关于 Nothing

的问题
  • 默认情况下,命名空间类型是内部的
  • 默认情况下,任何类型成员(包括嵌套类型)都是私有的

答案 4 :(得分:19)

enter image description here

using System;

namespace ClassLibrary1
{
    public class SameAssemblyBaseClass
    {
        public string publicVariable = "public";
        protected string protectedVariable = "protected";
        protected internal string protected_InternalVariable = "protected internal";
        internal string internalVariable = "internal";
        private string privateVariable = "private";
        public void test()
        {
            // OK
            Console.WriteLine(privateVariable);

            // OK
            Console.WriteLine(publicVariable);

            // OK
            Console.WriteLine(protectedVariable);

            // OK
            Console.WriteLine(internalVariable);

            // OK
            Console.WriteLine(protected_InternalVariable);
        }
    }

    public class SameAssemblyDerivedClass : SameAssemblyBaseClass
    {
        public void test()
        {
            SameAssemblyDerivedClass p = new SameAssemblyDerivedClass();

            // NOT OK
            // Console.WriteLine(privateVariable);

            // OK
            Console.WriteLine(p.publicVariable);

            // OK
            Console.WriteLine(p.protectedVariable);

            // OK
            Console.WriteLine(p.internalVariable);

            // OK
            Console.WriteLine(p.protected_InternalVariable);
        }
    }

    public class SameAssemblyDifferentClass
    {
        public SameAssemblyDifferentClass()
        {
            SameAssemblyBaseClass p = new SameAssemblyBaseClass();

            // OK
            Console.WriteLine(p.publicVariable);

            // OK
            Console.WriteLine(p.internalVariable);

            // NOT OK
            // Console.WriteLine(privateVariable);

            // Error : 'ClassLibrary1.SameAssemblyBaseClass.protectedVariable' is inaccessible due to its protection level
            //Console.WriteLine(p.protectedVariable);

            // OK
            Console.WriteLine(p.protected_InternalVariable);
        }
    }
}
 using System;
        using ClassLibrary1;
        namespace ConsoleApplication4

{
    class DifferentAssemblyClass
    {
        public DifferentAssemblyClass()
        {
            SameAssemblyBaseClass p = new SameAssemblyBaseClass();

            // NOT OK
            // Console.WriteLine(p.privateVariable);

            // NOT OK
            // Console.WriteLine(p.internalVariable);

            // OK
            Console.WriteLine(p.publicVariable);

            // Error : 'ClassLibrary1.SameAssemblyBaseClass.protectedVariable' is inaccessible due to its protection level
            // Console.WriteLine(p.protectedVariable);

            // Error : 'ClassLibrary1.SameAssemblyBaseClass.protected_InternalVariable' is inaccessible due to its protection level
            // Console.WriteLine(p.protected_InternalVariable);
        }
    }

    class DifferentAssemblyDerivedClass : SameAssemblyBaseClass
    {
        static void Main(string[] args)
        {
            DifferentAssemblyDerivedClass p = new DifferentAssemblyDerivedClass();

            // NOT OK
            // Console.WriteLine(p.privateVariable);

            // NOT OK
            //Console.WriteLine(p.internalVariable);

            // OK
            Console.WriteLine(p.publicVariable);

            // OK
            Console.WriteLine(p.protectedVariable);

            // OK
            Console.WriteLine(p.protected_InternalVariable);

            SameAssemblyDerivedClass dd = new SameAssemblyDerivedClass();
            dd.test();
        }
    }
}

答案 5 :(得分:15)

this answer重新发布真棒图表。

  

以下是维恩图中的所有访问修饰符,从更多限制到更多混杂:

     

private
  enter image description here

     

private protected: - added in C# 7.2
  enter image description here

     

internal
  enter image description here

     

protected
  enter image description here

     

protected internal
  enter image description here

     

public
  enter image description here

答案 6 :(得分:11)

嗯。

见这里:Access Modifiers

简而言之:

Public提供方法或从其他类型/类中键入完整的可见性。

Private只允许包含私有方法/变量的类型访问私有方法/变量(请注意,嵌套类也可以访问包含类私有方法/变量)。

受保护类似于private,但派生类也可以访问受保护的方法。

“没什么”是VB.NET相当于null。虽然如果你指的是“没有”意思是“没有访问修饰符”,那么它取决于,虽然一个非常粗略的经验法则(当然在C#中)是如果你没有明确指定访问修饰符,方法/变量声明通常是限制,因为它可以。 即

public class MyClass
{
    string s = "";
}

实际上与:

相同
public class MyClass
{
    private string s = "";
}

当没有明确指定访问修饰符时,链接的MSDN文章将提供完整描述。

答案 7 :(得分:8)

公开 - 任何人都可以访问。
私人 - 只能在其所属的班级中进行访问。
protected - 只能在类或从类继承的任何对象中访问。

没有什么比null更像是在VB中 静态意味着你有一个该对象的实例,该方法适用于该类的每个实例。

答案 8 :(得分:5)

然而,当前access modifier(C#7.2)的另一种可视化方法。希望该架构有助于更轻松地记住它
(单击图像以进行交互式查看。)

interactive access modifiers svg

外部内部

如果您想记住两个单词的访问修饰符,请记住 inside-inside

  • 受私有保护私有 外部(同一程序集)受保护 内部 (相同的程序集)
  • 受保护的内部受保护的 外部(同一程序集)内部 内部 (相同的程序集)

答案 9 :(得分:4)

嗯...

静态意味着您可以在没有类实例的情况下访问该函数。

您可以直接从课程定义中访问。

答案 10 :(得分:4)

Private的状态表示变量只能由同一个类的对象访问。受保护的状态扩展了该访问权限以包括该类的后代。

“从上表中我们可以看到私人和受保护之间的差异......我认为两者都是相同的...所以需要两个单独的命令”

查看MSDN链接以获取更多信息

答案 11 :(得分:3)

仔细观察您的课程的可访问性。默认情况下,每个人都可以访问公共和受保护的类和方法。

当创建Visual Studio中的新类时,Microsoft在显示访问修饰符(public,protected等等...关键字)方面也不是很明显。因此,请仔细考虑并考虑您的课程的可访问性,因为它是实施内部的大门。

答案 12 :(得分:3)

这些访问修饰符指定您的成员可见的位置。你应该读一读。以IainMH给出的链接为起点。

静态成员是每个类一个,而不是每个实例一个。

答案 13 :(得分:2)

我认为这与良好的OOP设计有关。如果您是库的开发人员,则希望隐藏库的内部工作方式。这样,您可以稍后修改库内部工作。因此,您将您的成员和帮助程序方法设置为私有,并且只有接口方法是公共的。应该保护应该覆盖的方法。

答案 14 :(得分:1)

C#总共 6 访问修饰符:

private :使用此辅助功能声明的成员可以在包含类型中可见,任何派生类型,相同程序集中的其他类型或包含程序集外部的类型都不可见。即,访问仅限于包含类型。

protected :使用此辅助功能声明的成员可以在从包含程序集中的包含类型派生的类型中可见,也可以在包含程序集外部的包含类型派生的类型中可见。即,访问仅限于包含类型的派生类型。

内部:使用此辅助功能声明的成员可以在包含此成员的程序集中可见,它对包含程序集外部的任何程序集都不可见。即访问仅限于包含程序集。

内部受保护:使用此辅助功能声明的成员可以在从包含程序集内部或外部的包含类型派生的类型中可见,对于包含程序集中的任何类型也是可见的。即,访问仅限于包含汇编或派生类型。

public :使用此辅助功能声明的成员可以在包含此成员的程序集中显示,也可以在引用包含程序集的任何其他程序集中可见。即访问不受限制。

C#7.2正在添加一个新级别的辅助功能:

private protected :使用此辅助功能声明的成员可以在包含程序集中从此包含类型派生的类型中可见。对于不是从包含类型派生的任何类型,或在包含程序集之外,它是不可见的。即,访问仅限于包含程序集中的派生类型。

Source including a sample code of the new private protected access modifier

答案 15 :(得分:1)

  • public 意味着它可以被任何程序集中的任何类访问,包括类本身。
  • protected internal 表示可以被类本身访问(在类定义中),当前程序集中的任何类都可以访问,但是程序集之外只能被类访问继承类,或由类本身(如果它是部分类) - 基本上它意味着internal在程序集内部和protected在程序集外部。
  • protected 表示它只能被类本身访问,或者被继承它的类访问并且该类可以在任何程序集中
  • internal 表示它可以被类本身或程序集中的任何类访问,但在程序集之外根本无法访问,除非类本身(即它是部分类)< /li>
  • private protected 表示它只能被类本身访问,或者它可以被继承它的类访问,并且只有该类在当前程序集中。在程序集之外,它只能被类本身访问(即它是一个部分类)——基本上结合了internalprotected,或者换一种说法是它是private程序集外部和程序集内部的 protected
  • private 表示只能被类本身访问
  • 无访问修饰符:The default access for everything in C# is "the most restricted access you could declare for that member".,对于类中的成员/方法/嵌套类为 private,对于非嵌套类为 internal

在上面的文本中'访问'意味着通过类类型的对象访问,在类本身的方法中将是隐式this对象,或者该方法实例化当前的显式对象类类型并通过该对象访问它。两者都被认为是由类本身访问的,因此访问规则是相同的。这也适用于从静态方法执行的访问,或者当它是正在访问的静态成员/方法时,除了使用类范围而不是和对象执行访问。静态类的成员/方法需要显式创建 static 否则将无法编译。

未嵌套的类可以是 publicinternal,默认情况下是 internal。嵌套的类可以是任何访问类型,如果父类是静态的,则它不需要是静态的,其成员也不需要是静态的。 internal 类意味着它只能被实例化或从当前程序集访问它的静态成员。

您可以在 internalprivate 嵌套类中拥有公共成员/方法/嵌套类——只有访问说明符(在进行的访问的完全限定名称中)低于当前访问所需的级别,阻止访问。

C# 中的继承总是 public 不像 C++,它可以私有或保护地继承,然后改变所有继承自该类的类的访问,以及通过object / via class 类的类型范围,该类从该类私有/受保护地继承,而从该类继承的类从该类继承/受保护地形成该类,依此类推。访问权限已更改,因此所有比 privateprotected 限制更少的访问修饰符都分别设为 privateprotected

答案 16 :(得分:-1)

对C#的所有访问修饰符的描述

enter image description here