C# Access Modifiers

  • Post published:June 13, 2020

Access modifiers are keywords in object-orientated programming (OOP) that are used to set the accessibility levels of types and type members. In C#, the accessibility level controls whether a type can be used within the current assembly or in other assemblies.

Access modifiers are used to assist with the implementation of the encapsulation OOP principle. C# provides four access modifiers (public, private, protected and internal) with the following accessibility levels.

  • public
  • private
  • protected
  • internal
  • protected internal
  • private protected

public

The public keyword is an access modifier providing an accessibility level that is not restricted. Types and type members utilizing the public modifier can be accessed everywhere, that is, there are no restrictions on accessing public members.

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

Microsoft

Consider the below code base.

In the above code base, the Hero class has a public accessibility level. This class can be accessed everywhere, that is, it can be accessed anywhere in the current assembly, AccessModifier, as well as any other assembly referencing the AccessModifier assembly. Likewise, The Id property and the Save method are also publicly available whenever a new Hero class is instantiated.

The public access modifier is the most commonly used accessibility level. Since this access modifier has no restrictions, developers should be cautious when using it.

private

The private keyword is an access modifier providing an accessibility level that is limited to the containing type.

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

Microsoft

Consider the below code base.

From the above code base, id, name and Save() can only be accessed within the Hero class, that is, the containing class. Nested types in the same body can also access those private methods.

A compile time error will be thrown when trying to access a private member outside the containing class or struct in which it is declared.

When members in a class have no access modifier, the default access modifier will be private.

protected

The protected keyword is an access modifier providing an accessibility level that is limited to the containing class or types derived from the containing class.

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

Microsoft

Consider the below code base.

In the above code base, the derived class, ChequeAccount, has direct access to the AccountNumber property from the base class, Account.

internal

The internal keyword is an access modifier providing an accessibility level that is limited to the current assembly.

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

Microsoft

Consider the below code base.

In the above code base, HeroRepository is only accessible within the AccessModifier assembly. The AccessModifier assembly is referenced in the SomeOtherAssembly, however, the SomeOtherAssembly cannot instantiate the HeroRepository due to the accessibility level of the HeroRepository.

When a class has no access modifier specified, then the class will have a default access modifier of internal.

Visual studio provides an easy way to make internal classes accessible to other assemblies for testing purposes. Refer to this article to set it up.

protected internal

protected internal provides an accessibility level that is limited to the current assembly or types derived from the containing class.

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.

Microsoft

Consider the below code base.

From the above code base, Account is a base class having a protected internal integer AccountNumber property. The derived class, ChequeAccount, has direct access to the AccountNumber property from the base class, Account, since both the Account and ChequeAccount are contained within the same assembly, AccessModifier.

The AccessModifier assembly is referenced in the SomeOtherAssembly, however, classes within the SomeOtherAssembly deriving from the Account base class cannot access the AccountNumber property due to the accessibility level of the AccountNumber.

Note that struct members cannot be protected internal because the struct cannot be inherited.

private protected

private protected provides an accessibility level that is limited to the containing class or types derived from the containing class within the current assembly.

The type or member can be accessed only within its declaring assembly, by code in the same class or in a type that is derived from that class.

Microsoft

Consider the below code base.

In the above code base, the derived class, ChequeAccount, has direct access to the AccountNumber property from the base class, Account.

SavingsAccount also has direct access to the AccountNumber property since it is derived from Account.

When a class is derived from Account and the derived class is instantiated, then the AccountNumber property cannot be accessed due to its accessibility level. This can be seen on lines 21 and 24 in the above code base.

However, when using classes derived from the containing class, the AccountNumber property is accessible. This can be seen on line 26 and 27 where the SavingsAccount derived class is instantiated within the SavingsAccount class.

Note that struct members cannot be private protected because the struct cannot be inherited.

Summary

Microsoft have provided an easy way for developers to implement certain OOP scenarios by using access modifiers with different accessibility levels, thus hiding unnecessary detail and only showing what is necessary during the implementation phase of a software program.

Further information on access modifiers and accessibility levels can be found at the following links:

Software versions used in this article

  • Jetbrains Rider 2020.1.3