In C#, what is the difference between public, private, protected, and having no access modifier?
Solution 1:
Access modifiers
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.
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(...);
Solution 2:
A graphical overview (summary in a nutshell)
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:
Solution 3:
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.
Solution 4:
Reposting the awesome diagrams from this answer.
Here are all access modifiers in Venn diagrams, from more limiting to more promiscuous:
private
:
private protected
: - added in C# 7.2
internal
:
protected
:
protected internal
:
public
:
Solution 5:
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.)
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)