Access Modifiers And Default Access Modifiers In C#

We have the following access modifiers available in C#.

  • Public
  • Private
  • Protected
  • Internal
  • Protected Internal

How to choose the appropriate access modifiers in our application is a big hurdle. Let’s try to find out the solution through few of the small implementations.

Level of Implementation/Access modifiers types At Namespace level At class Level At function level
Public yes yes
Private No yes
Protected No yes
Internal yes yes
Protected Internal No yes

I have tried to create a tabular view for simplification. Now, let’s try to explore what the table data shows.

The table column header shows where the implementation can be possible; i.e., at which level we are eligible to access which types of access modifiers.

Note: At function level everything is private; we cannot even explicitly declare private to a data member.

Implementation at Namespace level

Any element which can be defined atthe namespace level should have either public or internal access modifiers. Let’s prove the same.

error

Here we have tried to define a class of accessibility level as private, Interface with accessibility level as protected, enum with accessibility level as protected internal and a structure.

At the bottom of the screen we can clearly see the Error saying Error “Elements defined in a namespace cannot be explicitly declared as private, protected, or protected internal"

It means we are only left with the option of public or internal. Now how do we identify what is the default access modifiers for elements at namespace level? Friends, it is a very interesting and tricky interview question. I have been bombarded with the question, "What is the default access modifier in C#?" in many of the interviews I have appeared in as an interviewee.

I always thought it to be “internal,” however, I realized my conception was wrong when I tried to figure it out on my own. I understand when the question arises, what is the default access modifier in c#, we should ask the interviewer whether they want to know about the elements at namespace level or about the elements at class/function levels.

To get into the appropriate answer of this question, let refer few of the definition that MSDN site suggests.

  Within Namespace Outside Namespace
Public Access is not restricted. Accessible outside namespace.
Private Access is limited to containing type. Not accessible outside the namespace.
Protected Access is limited to the containing class or types derived from the containing class.  
Internal Access is limited to current assembly only. Not accessible.
Protected Internal Access is limited to the current assembly or types derived from the containing class. Outside the namespace, only accessible to the types derived from the containing class.

So far we have concluded that any element in namespace level is either public or internal. However, we have not yet reached any concrete statement yet.

However, let’s see outside “CheckAccessModifiers” assembly if we are able to access the Namespace level elements.

Steps:

  1. We have created two classes named MyCustomClass and MyCustomClass1 in namespace “CheckAccessModifiers”.
  2. Build the project. Create one more console project (in our example it is OutSideAssembly) at solution level.
  3. Add a reference of “OutSideAssembly” to “CheckAccessModifiers”.
  4. Include the namespace (using CheckAccessModifier)
  5. In Main () method try to access the elements of “CheckAccessModifiers” Namespace.

CheckAccessModifiers

Let’s see the below example. Here we have created another class named MyCustomClass1 and tried to access the members of MyCustomClass.

MyCustomClass1

We are only able to see “MyCustomClass1”.

Findings

The reference table from MSDN says, internal is only accessible in current assembly. Public modifiers can be accessed anywhere. If we recall it properly in our very first example, we saw elements at Namespace level can either be public or internal.

We had two classes named MyCustomClass and MyCustomClass1. The type of access modifiers they hold is unknown/default and public. Since at name space level we cannot use private/protected internal/protected.

MyCustomClass1 is accessible in namespace “OutSideAssembly” since it is declared as public, which means the default access modifier in C# at Namespace level element is “Internal”.

Implementation at Class Level and Function Level

To understand this concept, we have created three classes withinthe namespace “CheckAccessModifiers.” Currently, MyCustomClass is holding some data members of different access levels. MyCustomClass2 is inheriting from MyCustomClass.

We end up with two scenarios again. First we will check the behavior of the data members available in MyCustomClass within same namespace but inside different classes.

Scenario 1: (Within Namespace, outside class- In our case it is MyCustomClass1)

Within Namespace

After creating the object, we can see only fifthNumber, firstNumber and fouthNumber is available to us.

I.e. only members having modifiers either public/protected internal/internal is accessible in other classes.

Scenario 2: (Within Namespace, outside class inheriting from base class- in our case it is MyCustomClass2).

We are again having access to fifth, first, fourth and third variable. I.e. only members having modifiers either public/protected internal/internal/Protected is accessible in other classes.

accessible in other classes

Now we end up with a question, if public/protected internal/internal is available anywhere in the namespace how do we choose the appropriate access modifier at class level?

Let’s check the behavior outside the Namespace. We will follow to same steps and go to Namespace “OutSideAssembly”.

Below is the structure of classes in “OutSideAssembly” Assembly.

structure of classes

We have two more classes named Program and MyCustomClass3. MyCustomClass3 is inheriting from MyCustomClass. Our intention is to check the availability of data members outside the namespace.

Inside program class, when we try to access the following, is output.

output

Only firstNumber variable is available. This justifies the definition that public members have no restriction at all.

Let’s see the behavior inside MyCustomClass3.

MyCustomClass3

We are able to access first, fifth, and third variable.

On derived class examples whether it is within the namespace or outside the namespace, we saw that members with accessibility protected and protected internal is available in derived class.

Then how to choose when to Choose Protected and when to choose protected internal?

Solution

Friends this part is bit interesting, when we want any member to be available only in derived class within the same assembly but not to a normal class in other assembly, then one should go with Protected; however, if one is looking for a member which will be available anywhere in the current assembly but only in derived class in the outside namespace then one should choose protected internal.

Conclusion

Default access modifiers at Namespace level are internal.

Default access modifiers at Class level are private.

Default access modifiers at function level are private; we are not allowed to use even private keywords explicitly.

Read more articles on C# Programming: