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.
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:
- We have created two classes named MyCustomClass and MyCustomClass1 in namespace “CheckAccessModifiers”.
- Build the project. Create one more console project (in our example it is OutSideAssembly) at solution level.
- Add a reference of “OutSideAssembly” to “CheckAccessModifiers”.
- Include the namespace (using CheckAccessModifier)
- In Main () method try to access the elements of “CheckAccessModifiers” Namespace.
Let’s see the below example. Here we have created another class named MyCustomClass1 and tried to access the members of MyCustomClass.
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)
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.
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.
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.
Only firstNumber variable is available. This justifies the definition that public members have no restriction at all.
Let’s see the behavior inside 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: