C# Access Modifiers — Simple but still Confusing

Saumendra Mohapatra
5 min readMay 16, 2021

Whether we are beginner or experienced developer, we have all came across the access modifiers in our C# journey. This is one of the most basic concepts of building boundaries and also creating the path for different C# code modules to access each other.

We can easily find hundreds of tutorial and post online talking about it then why we need this Medium story? Here, we will try to understand C# Access Modifiers in a way (with examples) that we will not get confused about it in future.

So, we have six different access modifiers in C# but the most common among them is Public and Private. Now the readers of this story must be thinking, Here you go again! one more person talking about Public and Private. So, allow me to take you to more interesting modifiers other than this two in a minute.

Let’s take a pause now! I talked about understanding access modifiers with the help of examples and a bit of imagination. it’s time for us to imagine and code at the same time. The whole discussion will revolve around two assemblies. We will be able to see how we can create boundaries of restriction and at the same time, building a path for both assemblies to access each other.

Step 1: Open Visual Studio, Select “Continue Without Code ->

Step 2: Create new project, Select “Console Application (.NET Framework)

Step 3: Create a new project (note: please feel free the choose the name of your project and other details based on your own).

This is our first project/assembly in the solution.

Now it’s time to create another project under the same solution. I hope you remember at the start we talked about having two different project/assemblies to understand the access modifier and every time there is confusion, we just need to imagine how access modifiers work between two assemblies under the same solution.

Step 4: This is our Second project/assembly in the solution. Add “Class Library (.NET Framework)” project to the same solution.

After Step 4, we should be able to see the below project structure

Step 5: Build the Solution and add “Reference” of “StoreOfFunctionToAccess” to “CSharpeAccessModifiers

Step 6: Now we need to add three class to the assembly/project “StoreOfFunctionToAccess

  • StoreOfFunctions - This class will have six class method’s with all 6 types of C# access modifiers. Those access modifiers are: 1# Public, 2# Private, 3# Internal, 4# Protected Internal, 5# Protected, 6# Private Protected
  • AccessProtected - will implement (inherit) StoreOfFunctions class to show how it can access all 3 variation of Protected methods (Protected Internal, Private Protected and Protected) including Internal and Public methods.
  • AccessingPPII — will create a object of StoreOfFunctions to demonstrate that protected, private, private protected methods cannot be accessed due to their access levels.

The solution will look like below after adding 3 classes to assembly/project “StoreOfFunctionToAccess

Step 7: Now we need to add one class “CSharpeAccessModifiers” to the project/assembly CSharpeAccessModifiers. We are creating this to show how access modifiers works while accessing another project/assembly’s classes and their methods which is present in the same solution.

Now the below shows the pictorial representation of two assemblies/projects and their underlying classes, methods and also shows how access modifiers work to create restrictions and access path.

In summary, there are 6 types of Access Modifiers in the C# language. The basic and most commonly used access modifier is : Public and Private.

  • Public- There are no restrictions for this modifier. As per our example, method’s (PublicMethod) defined with Public access modifiers are accessible in both assemblies/project.

Example: As shown above, PublicMethod() is defined in class “StoreOfFunctions” but it is accessible everywhere (in CSharpeAccessModifiers and StoreOfFunctionToAccess project).

  • Private- It is only accessible where it is defined (in our example only in the class “StoreOfFunctions” and nowhere else).
  • Internal- Anyone can access It within the same assembly/project where it is defined. In our example, anyone in StoreOfFunctionToAccess assembly/project will be able to access methods defined as Internal.

Example: Two classes (AccessProtected, AccessingPPII) defined in StoreOfFunctionToAccess are able access method InternalMethod().

  • Protected- restrict access based on inheritance. To have access to the protected method, we need to implement/inherit the Parent class first.

Example: AccessProtected class in assembly StoreOfFunctionToAccess inherited StoreOfFunctions and then able to access methods (ProtecedMethod).

  • Protected Internal- Now we are stepping into more interesting access modifiers. let’s break this down to understand it easily. “Protected” means, assemblies/projects which is not current to the method need to inherit the parent class to access the methods. But, adding “internal” to “protected” means the method can be accessible in current assembly with or without the inheriting the parent class.

Example: “ProtectedInternalMethod()” is accessible everywhere in assembly/project “StoreOfFunctionToAccess” where it belongs to and it acts as “internal”. However, other assemblies/project needs to inherit “StoreOfFunction” to access the protected internal method “ProtectedInternalMethod()”.

CSharpeAccessModifiers implemented StoreOfFunctions to access ProtectedInternalMethod() Metod
AccessingPPII did not have to implement/inherit StoreOfFunctions and still able to access ProtectedInternalMethod()
  • Private Protected - it’s a combination of “Private” and “Protected”. It acts as a “Private” for external assemblies/projects and “Protected” for parent assembly.

Example: “AccessProtected” class inherited “StoreOfFunctions” and able to access “PrivateProtecedMethod()”. However, “CSharpeAccessModifiers” class inherited “StoreOfFunctions” but still cannot access “PrivateProtecedMethod()”.

CSharpeAccessModifiers implemented StoreOfFunctions but still cannot access PrivateProtecedMethod() because it is defined in another assembly/project (i.e., StoreOfFunctionToAccess)

The below table shows the overall access matrix based on the access modifiers and access areas.

Conclusion

Access modifiers have to be used in a manner that not only satisfies your application need but also ensure the application’s data accessibility is secured.

--

--