A Beginner's Guide to C# Access Modifiers: Learn the Basics

Search for a command to run...

No comments yet. Be the first to comment.
What is a delegate? a delegate is a reference type variable that holds the reference of a method. C# delegates are similar to the C / C++ equivalent of pointers to the method - a delegate holds the address of a method that can be called using the del...
ASP.NET Core Configuration Guide Overview ASP.NET Core uses a layered configuration system where later sources override earlier ones for the same key. Configuration Priority Order Priority Source
Legacy Delphi applications often struggle with outdated UI/UX, performance issues, and monolithic architectures that make refactoring difficult. However, a full rewrite is not always feasible due to time, cost, and the risk of disrupting critical bus...
Entity Framework Core (EF Core) is a powerful and flexible object-relational mapping (ORM) framework for .NET applications, enabling developers to work with relational databases using strongly-typed .NET objects. It simplifies data access by abstract...

In this article we are going to cover some advance scenarios where Options pattern is very useful. We have covered the basic understanding of Options pattern into Options pattern in ASP.NET Core: Introduction article. Please go through it if not fami...

In this article we will learn about Options pattern in ASP.NET Core for dealing with application configurations. The Options pattern uses the C# classes to access and manage the configurations thus providing more flexibility and type safe approach to...

Access modifiers determine the accessibility of a type or type member, indicating which parts of a C# program can access those types and their members. By protecting types and members from unintended access, access modifiers contribute to achieving encapsulation.
Below is the list of all the access modifiers used in the C# language
type or members with private access modifiers could be accessed by any code in the same assembly or another assembly referencing it.
public is the default access modifier for members of an enum or interface.
accessibility of public members is controlled by the access modifier of the type itself.
Code example
using System;
namespace AccessModifierCode {
class Employee {
public int EmpId;
public string Name;
public Employee(int empid, string name) {
EmpId = empid;
Name = name;
}
}
class Program {
static void Main(string[] args) {
// Creating object of the class Employee
Employee E = new Employee(1, "Deepak");
Console.WriteLine("Emp Id: {0}", E.EmpId);
Console.WriteLine("Name: {0}", E.Name);
Console.WriteLine();
}
}
}
members declared with private access modifier are accessible only within the containing type.
private access modifier is the most restrictive one.
one can not declare a private class or struct directly inside a namespace.

private is the default accessibility for members of a class or struct.
public class Demo {
string Name; // private
}
using System;
namespace AccessModifierCode {
class Employee {
public int EmpId;
public string Name;
private decimal Salary
public Employee(int empid, string name, decimal salary) {
EmpId = empid;
Name = name;
Salary = salary;
}
}
class Program {
static void Main(string[] args) {
// Creating object of the class Employee
Employee E = new Employee(1, "Deepak", 0);
Console.WriteLine("Emp Id: {0}", E.EmpId);
Console.WriteLine("Name: {0}", E.Name);
Console.WriteLine("Salary: {0}", E.Salary);
// Error : 'Employee.Salary is inaccessible due to its protection level'
Console.WriteLine();
}
}
}
types or members declared with internal modifiers are accessible within the same assembly or friend assembly. Learn more about Friend assembly
internal is the default access modifier for class and struct types.
protected type or members are accessible within the same class or derived class.
public class Shape {
protected int Width { get; set; }
protected int Height { get; set; }
}
public class Rectangle : Shape {
public Rectangle(int width, int height) {
Width = width;
Height = height;
}
}
protected internal modifier can be accessed only within the same assembly or in a derived class from another assembly.private protected is accessible only within the containing type, or subclasses that reside in the same assembly (making it less accessible than protected or internal alone).Interfaces declared directly within a namespace can be public or internal and, just like classes and structs, interfaces default to internal access.
Interface members are public by default.
Enumeration members are always public, and no access modifiers can be applied.
Delegates function similarly to classes and structs. When declared directly within a namespace, they have internal access by default, and when nested, they have private access.
Derived classes and derived records can't have greater accessibility than their base types. You can't declare a public class B that derives from an internal class A. If allowed, it would have the effect of making A public, because all protected or internal members of A are accessible from the derived class.
When overriding a base class function, accessibility must be identical to the over‐ ridden function.
class BaseClass {
protected virtual void Foo() {}
}
class Subclass1 : BaseClass {
protected override void Foo() {} // OK
}
class Subclass2 : BaseClass {
public override void Foo() {} // Error
}
| 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) | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ |
(note: copied from MS learn)
So, that concludes our discussion on access modifiers. In this article, we covered the six access modifiers in C#: public, private, protected, internal, protected internal, and private protected. We learned about the purpose of each access modifier and their applications.
By employing the appropriate access modifier, we can ensure that our code is secure, user-friendly, and easy to maintain. Ultimately, this allows us to establish a clear and consistent structure for our code.
References and further reading