795

All my college years I have been using public, and would like to know the difference between public, private, and protected?

Also what does static do as opposed to having nothing?

neaumusic
  • 10,027
  • 9
  • 55
  • 83
MrM
  • 21,709
  • 30
  • 113
  • 139

20 Answers20

1089

Access modifiers

From learn.microsoft.com:

public

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

private

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

protected

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

private protected (added in 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.

internal

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

protected internal

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

When no access modifier is set, a default access modifier is used. So there is always some form of access modifier even if it's not set.

static modifier

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:

static class Foo()
{
    static Foo()
    {
        Bar = "fubar";
    }
    
    public static string Bar { get; set; }
}

Static classes are often used as services, you can use them like so:

MyStaticClass.ServiceMethod(...);
Community
  • 1
  • 1
mbillard
  • 38,386
  • 18
  • 74
  • 98
  • 19
    And you can have static methods in non-static classes, right? – John B Mar 05 '09 at 17:19
  • 15
    Yes, they would behave the same way as in my example. – mbillard Mar 05 '09 at 17:56
  • 9
    What does the term "assembly" mean in this context? – Jonathan Gleason Dec 10 '14 at 20:47
  • 1
    Static - also, think of it as being a global variable. Example: Console.WriteLine() ... Console is a static class as are all of its methods. Hence, they can easily be used anywhere in the code by using this form - [static class].[static method]() as in Console.WriteLine(). – nanonerd Dec 21 '15 at 13:59
  • 1
    Please note, that there is a new access modifier coming up in C# 7.2 called `private protected`. Please have a look at: (https://blogs.msdn.microsoft.com/mazhou/2017/10/05/c-7-series-part-5-private-protected/) – Baccata Dec 20 '17 at 09:03
  • 3
    What is the difference between Protected and Private Protected ? To me , it sounds both are same .. – goofyui Jul 12 '18 at 13:39
  • 2
    @goofyui, the difference is that `protected` members are accessible in derived classes in **any assembly**. `private protected` members are only accessible in derived classes in **same assembly**. – Paul Smith Jan 16 '20 at 20:24
  • @JonathanGleason https://learn.microsoft.com/en-us/dotnet/standard/glossary#assembly I think it also refers to "projects" in the context of VS. – carloswm85 Jun 20 '22 at 16:16
  • What about `record`(s)? It mentions classes and structs only, which I think it may be insufficient information to common types. – carloswm85 Jun 20 '22 at 16:18
206

A graphical overview (summary in a nutshell)

Visibility

Actually, it's a little bit more complicated than that.
Now (as of C# 7.2), there's also private protected, and it matters whether a derived class is in the same assembly or not.

So the overview needs to be expanded:

Visibility expanded

See also the C#-dotnet-docs on the subject.

Since static classes are sealed, they cannot be inherited (except from Object), so the keyword protected is invalid on static classes.



For the defaults if you put no access modifier in front, see here:
Default visibility for C# classes and members (fields, methods, etc.)?

Non-nested

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:

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

Also, there is the sealed-keyword, which makes a class not-inheritable.
Also, in VB.NET, the keywords are sometimes different, so here a cheat-sheet:

VB vs. CS equivalents

Stefan Steiger
  • 78,642
  • 66
  • 377
  • 442
  • 1
    @ᴀʀᴜn BᴇrtiL: Are you sure ? A derived class in a different assembly ? – Stefan Steiger Jan 08 '15 at 11:02
  • derived class in the same assembly we can,different we can't.I thought you meant like in the same assembly... – Arun Bertil Jan 08 '15 at 11:44
  • 1
    @ᴀʀᴜn BᴇrtiL: Hmm, right, this should actually be hatched. – Stefan Steiger Apr 21 '15 at 08:29
  • 1
    I think there is an error in the diagram. If internal is used for a class, the class can be derived by another class in the same assembly. Also if the internal modifier is used on a property, this property can also be accessed in the derived class in the same assembly. Perhaps the diagram is correct because there is a "yes" under "containing assembly", but it can be misunderstood because there is a "no" under "derived classes". – AH. Oct 06 '16 at 10:43
167

Public - If you can see the class, then you can see the method

Private - If you are part of the class, then you can see the method, otherwise not.

Protected - Same as Private, plus all descendants can also see the method.

Static (class) - Remember the distinction between "Class" and "Object" ? Forget all that. They are the same with "static"... the class is the one-and-only instance of itself.

Static (method) - Whenever you use this method, it will have a frame of reference independent of the actual instance of the class it is part of.

JosephStyons
  • 57,317
  • 63
  • 160
  • 234
  • 1
    Can't you have static methods in a non static class though? – John B Mar 05 '09 at 17:17
  • 1
    Yes, but I was talking about a static class. I added a separate entry to describe static methods. Thanks for the catch. – JosephStyons Mar 05 '09 at 17:22
  • 2
    'Object' might not be a good term here when talking about C#, as the base-type for all classes is *System.Object*. 'Instance' would be a better word, or 'object' (lowercase 'O'). – lesderid Jul 16 '12 at 15:03
  • @lesderid 'object' is an alias of 'System.Object', using it might be confusing too. 'instance' would be better, I guess :) – kazinix Jul 05 '13 at 10:12
  • same rules applies to structs. – gsharp Jul 18 '14 at 07:11
  • @dpp and @lesderid `instance` is not better than `object` because it implies an instantiation of an object. – NappingRabbit Aug 24 '17 at 18:52
56

Reposting the awesome diagrams from this answer.

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

Pang
  • 9,564
  • 146
  • 81
  • 122
Paul
  • 6,061
  • 6
  • 39
  • 70
37

Yet another visual approach of the current access modifier (C# 7.2). Hopefully the schema helps to remember it easier
(click the image for interactive view.)

interactive access modifiers svg

Outside Inside

If you struggle to remember the two-worded access modifiers, remember outside-inside.

  • private protected: private outside (the same assembly) protected inside (same assembly)
  • protected internal: protected outside (the same assembly) internal inside (same assembly)
user1810087
  • 5,146
  • 1
  • 41
  • 76
26

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();
        }
    }
}
Narottam Goyal
  • 3,534
  • 27
  • 26
  • 1
    I don't see what this answer adds over the many other answers from the past five years. – John Saunders May 24 '15 at 07:22
  • 4
    This is just a simple explanation. As other answers are bit confusing and half answered :) – Narottam Goyal May 24 '15 at 07:27
  • 4
    @John Saunders: It differentiates by separating the visibility for a derived class between that class being in the same and that class being in a different assembly. Plus he provides how he got to that information by showing his sample code. So it actually adds to the other answers. His necromancing was probably triggered by my comment in my answer. – Stefan Steiger Jul 08 '16 at 06:59
  • 2
    "Derived class in different assembly" - this adds value to the chart already given in another answer. The difference is helpful especially in case of "protected internal" – Nirman Jan 25 '18 at 05:26
  • I find this chart to be the easiest for me to understand. To keep this current (with C# 7.2), to add `Private Protected`, it would be: same class = `Yes`, same assembly, derived class = `Yes`, same assembly, any class = `NO`, different assembly, derived class = `NO`, different assembly, any class = `NO`. One additional suggestion also would be not to switch word order for `protected internal`, as this breaks the pneumonic from @user1810087's answer – Intrastellar Explorer Oct 20 '19 at 21:19
23

Regarding the question of Nothing

  • Namespace types are internal by default
  • Any type member, including nested types are private by default
leppie
  • 115,091
  • 17
  • 196
  • 297
12

Hmm.

See here: Access Modifiers.

In a nutshell:

Public gives the method or type complete visibility from other types/classes.

Private allows only the type containing the private method/variable access to the private method/variable (note that nested classes also have access to the containing classes private methods/variables).

Protected is similar to private except derived classes can also access protected methods.

"Nothing" is VB.NET's equivalent to null. Although if you're referring to "nothing" meaning "no access modifier", then it depends, although a very rough rule of thumb (certainly in C#) is that if you don't explicitly specify an access modifier, the method/variable declaration is usually as restricted as it can be. i.e.

public class MyClass
{
    string s = "";
}

is effectively the same as:

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

The linked MSDN article will offer a fully description when there's no access modifier explicitly specified.

ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
CraigTP
  • 44,143
  • 8
  • 72
  • 99
12

public - can be access by anyone anywhere.
private - can only be accessed from with in the class it is a part of.
protected - can only be accessed from with in the class or any object that inherits off of the class.

Nothing is like null but in VB.
Static means you have one instance of that object, method for every instance of that class.

Johnny Bones
  • 8,786
  • 7
  • 52
  • 117
Tony
  • 1,684
  • 1
  • 18
  • 29
5

A status of Private indicates that variables can only be accessed by objects of the same class. Protected status extends that access to include descendants of the class as well.

"from the above table we can see the deference between private and protected... am think both are same ....so what the need for that two separate command"

Check MSDN link for more information

radu florescu
  • 4,315
  • 10
  • 60
  • 92
Grant Hood
  • 51
  • 1
  • 1
5

mmm...

Static means that you can access that function without having an instance of the class.

You can access directly from the class definition.

gbianchi
  • 2,129
  • 27
  • 35
5
  • public means that it can be accessed by any class in any assembly, which includes the class itself.
  • protected internal means it can be accessed by the class itself (in the class definition), and it can be accessed by any class in the current assembly, but outside of the assembly it can only be accessed by a class that inherits the class, or by the class itself (if it is a partial class) – basically it means internal inside the assembly and protected outside of the assembly.
  • protected means it can only be accessed by the class itself, or accessed by a class that inherits it and that class can be in any assembly
  • internal means it can be accessed by the class itself or by any class in the assembly but can't be accessed at all outside of the assembly unless by the class itself (i.e. it is a partial class)
  • private protected means it can only be accessed by the class itself, or it can be accessed by a class that inherits it and only if that class is in the current assembly. Outside of the assembly, it can only be accessed by the class itself (i.e. it is a partial class) – basically combines internal and protected, or another way of putting it is it's private outside of the assembly and protected inside the assembly.
  • private means that it can only be accessed by the class itself
  • no access modifier: The default access for everything in C# is "the most restricted access you could declare for that member"., which is private for a member / method / nested class in a class and internal for a non-nested class.

In the above text 'accessed' means accessed via an object of the class type, which within a method of the class itself will be the implicit this object, or perhaps the method instantiates an explicit object of the current class type and accesses it through that object. Both are considered to be being accessed by the class itself and therefore the access rules are the same. This also applies to an access being performed from a static method, or when it is a static member / method being accessed, except the access is performed using the class scope and not and object. A member / method of a static class needs to be explicitly made static or it won't compile.

Classes that are not nested can either be public or internal and are internal by default. Classes that are nested can be any access type, and if the parent class is static, it does not need to be static and neither do its members. An internal class means that it can only be instantiated or its static members accessed from the current assembly.

You can have a public member / method / nested class in an internal or private nested class -- only the access specifier (in the fully qualified name of the access that is being made) that is below the level required in the current access that is being made prevents the access.

Inheritance in C# is always public unlike C++, which can privately or protectedly inherit, which then changes the access of all classes that then inherit from the class that is inheriting from this class, as well as the access via object / via class scope of type of the class that inheriting privately / protectedly from the class and the class that is inheriting from the class that is inheriting privately / protectedly form the class, and so on. The access is changed such that all access modifiers less restrictive than private or protected are made private and protected respectively.

Lewis Kelsey
  • 4,129
  • 1
  • 32
  • 42
4

Careful! Watch the accessibility of your classes. Public and protected classes and methods are by default accessible for everyone.

Also, Microsoft isn't very explicit in showing access modifiers (public, protected, etc.. keywords) when new classes in Visual Studio are created. So, take good care and think about the accessibility of your class because it's the door to your implementation internals.

Pang
  • 9,564
  • 146
  • 81
  • 122
Patrick Peters
  • 9,456
  • 7
  • 57
  • 106
3

C# has, in total, 6 access modifiers:

private: The member declared with this accessibility can be visible within the containing type, it is not visible to any derived types, other types in the same assembly or types outside of the containing assembly. i.e., access is limited to the containing type only.

protected: The member declared with this accessibility can be visible within the types derived from the containing type within the containing assembly, and the types derived from the containing type outside of the containing assembly. i.e., access is limited to derived types of the containing type.

internal: The member declared with this accessibility can be visible within the assembly containing this member, it is not visible to any assembly outside of the containing assembly. i.e., access is limited to containing assembly only.

internal protected: The member declared with this accessibility can be visible within the types derived from the containing type within or outside of the containing assembly, it is also visible to any types within the containing assembly. i.e., access is limited to containing assembly or derived types.

public: The member declared with this accessibility can be visible within the assembly containing this member, or any other assembly that references the containing assembly. i.e., access is not limited.

In C# 7.2, a new level of accessibility was added:

private protected: The member declared with this accessibility can be visible within the types derived from this containing type within the containing assembly. It is not visible to any types not derived from the containing type, or outside of the containing assembly. i.e., the access is limited to derived types within the containing assembly.

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

Pang
  • 9,564
  • 146
  • 81
  • 122
Baccata
  • 473
  • 1
  • 7
  • 15
3

Those access modifiers specify where your members are visible. You should probably read this up. Take the link given by IainMH as a starting point.

Static members are one per class and not one per instance.

jpfollenius
  • 16,456
  • 10
  • 90
  • 156
3

I think it is related to good OOP design. If you are a developer of a library you want to hide the inner workings of your library. That way, you can modify your library inner workings later on. So you put your members and helper methods as private, and only interface methods are public. Methods that should be overwritten should be protected.

Chazt3n
  • 1,641
  • 3
  • 17
  • 42
Darius Kucinskas
  • 10,193
  • 12
  • 57
  • 79
2

All access modifiers' descriptions for C#

enter image description here

2

I have created another type of visualization. Maybe this can be better way to understand for someone

https://github.com/TropinAlexey/C-sharp-Access-Modifiers

enter image description here

Tropin Alexey
  • 606
  • 1
  • 7
  • 16
2

public The type or member can be accessed by any other code in the same assembly or another assembly that references it. The accessibility level of public members of a type is controlled by the accessibility level of the type itself.

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

internal Internal types or members are accessible only within files in the same assembly.

protected The type or member can be accessed only by code in the same class, or in a class that is derived from that class. internal: The type or member can be accessed by any code in the same assembly, but not from another assembly. In other words, internal types or members can be accessed from code that is part of the same compilation. protected internal: The type or member can be accessed by any code in the assembly in which it's declared, or from within a derived class in another assembly.

private protected The type or member can be accessed by types derived from the class that are declared within its containing assembly.

protected internal A protected internal member is accessible from the current assembly or from types that are derived from the containing class.

static modifier is used to declare a static member, which belongs to the type itself rather than to a specific object. The static modifier can be used to declare static classes. In classes, interfaces, and structs, you may add the static modifier to fields, methods, properties, operators, events, and constructors.

With C# 11 you can also use the file access modifier.

The file modifier restricts a top-level type's scope and visibility to the file in which it's declared. The file modifier will generally be applied to types written by a source generator. File-local types provide source generators with a convenient way to avoid name collisions among generated types.

// In File1.cs:
file interface IWidget
{
    int ProvideAnswer();
}

file class HiddenWidget
{
    public int Work() => 42;
}

public class Widget : IWidget
{
    public int ProvideAnswer()
    {
        var worker = new HiddenWidget();
        return worker.Work();
    }
}
Darren
  • 68,902
  • 24
  • 138
  • 144
0

Given that all sites across Stack Exchange, including Stack Overflow, now supports markdown tables I was missing one from the answers here.

Summary table:

Caller's location public protected internal protected internal private protected private
Within the class ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
Derived class (same assembly) ✔️ ✔️ ✔️ ✔️ ✔️
Non-derived class (same assembly) ✔️ ✔️ ✔️
Derived class (different assembly) ✔️ ✔️ ✔️
Non-derived class (different assembly) ✔️

Source:

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers#summary-table

https://meta.stackexchange.com/questions/356997/new-feature-table-support

Ogglas
  • 62,132
  • 37
  • 328
  • 418