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

问题描述 投票:680回答:15

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

static做什么而不是什么都没有?

c# .net asp.net access-modifiers
15个回答
958
投票

访问修饰符

来自docs.microsoft.com

上市

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

私人的

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

保护

类型或成员只能由同一类或结构中的代码或派生类访问。

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

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

内部

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

保护内部

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

如果未设置访问修饰符,则使用默认访问修饰符。因此,即使没有设置,也总会有某种形式的访问修饰符。

静态的

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

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

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

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

    public static string Bar { get; set; }
}

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

MyStaticClass.ServiceMethod(...);

4
投票

嗯...

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

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


4
投票

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

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

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


3
投票

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

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


3
投票

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

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


2
投票

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


1
投票

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

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

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

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

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

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

C#7.2正在增加一个新的可访问性级别:

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

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


155
投票

公共 - 如果您可以看到该类,那么您可以看到该方法

私人 - 如果您是班级的一员,那么您可以看到该方法,否则不会。

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

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

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


146
投票

图形概述(简要总结)

对于默认值,如果您没有在前面放置访问修饰符,请参见此处: 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

22
投票

关于什么都没有

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

20
投票

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();
        }
    }
}

16
投票

this answer重新发布令人敬畏的图表。

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

private

private protected - added in C# 7.2

internal

protected

protected internal

public


11
投票

嗯。

见这里:Access Modifiers

简而言之:

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

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

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

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

public class MyClass
{
    string s = "";
}

实际上与以下内容相同:

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

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


8
投票

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

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


5
投票

当前access modifier的另一种视觉方法(C#7.2)。希望架构有助于更容易地记住它 (单击图像以获取交互式视图。)

interactive access modifiers svg

在室外

如果你很难记住两个措辞的访问修饰符,请记住内外。

  • private protected:私有外部(同一个程序集)受保护(同一个程序集)
  • 受保护的内部:受保护的外部(相同的组件)内部(相同的组件)
© www.soinside.com 2019 - 2024. All rights reserved.