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

In C#, what is the difference between public, private, protected, and having no access modifier?

我大学的时候一直在使用public,想知道publicprivateprotected之间的区别吗?

还有,与什么都没有相比,static做了什么?


访问修饰符

From docs.microsoft.com

public

The type or member can be accessed by any other code in the same assembly or another assembly that references it.

私有的

The type or member can only be accessed by code in the same class or struct.

受保护的

The type or member can only be accessed by code in the same class or struct, or in a derived class.

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

The type or member can only be accessed by code in the same class or struct, or in a derived class from the same assembly, but not from another assembly.

内部的

The type or member can be accessed by any code in the same assembly, but not from another assembly.

内部受保护

The type or member can be accessed by any code in the same assembly, or by any derived class in another assembly.

< /块引用>

如果未设置访问修饰符,则使用默认访问修饰符。所以总是有某种形式的访问修饰符,即使它没有被设置。

静态的

The static modifier on a class means that the class cannot be instantiated, and that all of its members are static. A static member has one version regardless of how many instances of its enclosing type are created.

A static class is basically the same as a non-static class, but there is one difference: a static class cannot be externally instantiated. In other words, you cannot use the new keyword to create a variable of the class type. Because there is no instance variable, you access the members of a static class by using the class name itself.

However, there is a such thing as a static constructor. Any class can have one of these, including static classes. They cannot be called directly & cannot have parameters (other than any type parameters on the class itself). A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced. Looks like this:

1
2
3
4
5
6
7
8
9
static class Foo()
{
    static Foo()
    {
        Bar ="fubar";
    }

    public static string Bar { get; set; }
}

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

1
MyStaticClass.ServiceMethod(...);


public-如果可以看到类,那么可以看到方法

private-如果您是类的一部分,那么您可以看到该方法,否则不能。

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

静态(类)-记得"类"和"对象"之间的区别吗?忘了这些。它们与"静态"相同…类是其自身的唯一实例。

静态(方法)-无论何时使用此方法,它都有一个独立于它所属类的实际实例的引用框架。


图形概述(简而言之)

Visibility

对于默认值,如果前面没有放置访问修饰符,请参见此处:
C类和成员(字段、方法等)的默认可见性?

非嵌套的

1
2
3
4
5
6
enum                              public
non-nested classes / structs      internal
interfaces                        internal
delegates in namespace            internal
class/struct member(s)            private
delegates nested in class/struct  private

嵌套的:

1
2
3
4
nested enum      public
nested interface public
nested class     private
nested struct    private


关于什么都没有的问题

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

enter image description here

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
 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();
        }
    }
}


从这个答案中重新发布很棒的图表。

Here are all access modifiers in Venn diagrams, from more limiting to more promiscuous:

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


隐马尔可夫模型。

请参见此处:访问修饰符。

简而言之:

public提供方法或类型从其他类型/类的完全可见性。

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

protected类似于private,但派生类也可以访问protected方法。

"Nothing"是vb.net等价于空值。虽然如果您所指的"无"意味着"无访问修饰符",那么它取决于,尽管一个非常粗略的经验法则(当然是在C)是,如果您没有显式地指定访问修饰符,方法/变量声明通常会受到尽可能多的限制。即

1
2
3
4
public class MyClass
{
    string s ="";
}

实际上与以下内容相同:

1
2
3
4
public class MyClass
{
    private string s ="";
}

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


公共-任何人都可以访问。private-只能从它所属的类中的和访问。Protected-只能从类中的和或从类继承的任何对象访问。

除了在vb中,没有什么像null。静态意味着您拥有该对象的一个实例,该类的每个实例的方法。


当前访问修改器的另一种可视化方法(C 7.2)。希望这个模式能帮助我们更容易地记住它。(单击图像进行交互视图。)

interactive access modifiers svg

外面

如果您很难记住两个单词的访问修饰符,请记住外部内部。

  • 私有保护:私有外部(同一程序集)保护内部(同一程序集)
  • 内部保护:外部保护(同一组件)内部保护(同一组件)

private状态表示变量只能由同一类的对象访问。受保护状态将该访问扩展到包含类的后代。

"从上表我们可以看到私人和受保护之间的尊重……我认为两者都是一样的……那么这两个单独的命令的需要是什么呢?"

有关详细信息,请查看msdn链接


嗯…

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

您可以直接从类定义访问。


仔细观察你的类的可访问性。默认情况下,所有人都可以访问公共和受保护的类和方法。

此外,微软在显示访问修饰符(public、protected等)方面也不是很明确。关键字)在Visual Studio中创建新类时。所以,要注意并考虑类的可访问性,因为它是实现内部的门。


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

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


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


C总共有6个访问修饰符:

private:用此可访问性声明的成员可以在包含类型内可见,对于任何派生类型、同一程序集中的其他类型或包含程序集之外的类型都不可见。也就是说,访问仅限于包含类型。

受保护:用此可访问性声明的成员可以在从包含程序集中的包含类型派生的类型内可见,也可以在包含程序集中外部的包含类型派生的类型内可见。即,访问仅限于包含类型的派生类型。

内部:用此可访问性声明的成员可以在包含此成员的程序集中可见,但在包含程序集之外的任何程序集都不可见。也就是说,访问仅限于包含组件。

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

public:使用此可访问性声明的成员可以在包含此成员的程序集中或引用包含程序集的任何其他程序集中可见。也就是说,访问不受限制。

C 7.2增加了一个新的可访问性级别:

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

包含新的私有保护访问修饰符的示例代码的源