Java has four categories of protection access for methods and variables:
private
protected
(default, or package – no access modifier specified)
public.
C# has five categories of protection access:[1]
[1] If you have done C++ before, you might have heard of C++'s friend keyword. Both Java and C# have discarded the 'friend function' feature of C++. friend is not a keyword in both Java and C#.
private
protected
internal
internal protected
public.
Java's default (also known as package) accessibility is no longer there, and there is a new accessibility category based on the internal modifier in C#.
Table 8.1 shows more information about C#'s accessibility options.
Table 8.2 shows the applicable accessibility modifiers for the various types/ members in C#, together with their default accessibility if no accessibility modifier is specified in their declarations. Note that no access modifiers are allowed in the declaration of namespaces, interface members, and enumeration members – although these types/members do have a default implicit accessibility level.
Access modifier | Meaning |
---|---|
public | Access unlimited (same as Java) |
protected | Access limited to enclosing type and subtypes (same as Java) |
internal | Access limited to this program (i.e. all codes in the same source file) |
protected internal | Access limited to this program and types derived from the enclosing type (even if it is coded outside this program) |
private | Access limited to the enclosing type only (same as Java) |
Category | Applicable accessibility modifiers | Default accessibility |
---|---|---|
Namespaces [1] | (implicit) public | public |
Classes, interfaces, and structs declared within a namespace | public, internal | internal |
Class members [2] | public, protected, internal, protected internal, private | private |
Struct members [3] | public, internal, private | private |
Interface members [1] | (implicit) public | public |
Enumeration members [1] | (implicit) public | public |
[1] No access modifiers are allowed in the declaration of namespaces, interface members, and enumeration members.
[2] Class members include constants, fields, methods, properties, events, indexers, operators, constructors, destructors, and other methods.
[3] structs are implicitly sealed.
The accessibility of a type member is established by both:
the declared accessibility of the member itself; and
the accessibility of its enclosing type.
For example, a field declared as public in a class which has internal accessibility will not be accessible from another class written in a separate program. You must be able to have access to the class before you can access its members even though it may seem that a member's accessibility is less strict (more accessible) than its enclosing type. Both factors have to be considered when determining the final accessibility of a member.
For Java, variables or methods declared with no access modifiers will be given 'default' accessibility protection. For C#, if no access modifiers are used in the declaration of variables and methods, the default protection is private. [2] Refer to Table 8.2 for the default accessibility levels for other types in C#.
[2] I think that this is a good move on the part of C#. Good OO programming principles dictate that class members should be 'as private as possible', and this feature of C# helps developers who omit the accessibility modifier (whether on purpose or through laziness) attain this goal whether they like it or not!
You will realize that unlike Java, whereby accessibility is often affected by whether a class is in a particular package, namespaces in C# do not play a role in accessibility.
I have presented several examples below to illustrate the accessibility domain of a class member declared as internal and protected internal because these are the special accessibility levels not applicable in Java.
Let's explore the internal accessibility modifier first. Study Source1.cs below:
1: // Source1.cs
2:
3: namespace NameSpace1{
4: public class A{
5: internal static int X;
6: protected internal static int Y;
7: public static int Z;
8:
9: static void DoThis(){
10: X = 1;
11: }
12:
13: class NestedA{
14: static void DoThis(){
15: A.X = 1;
16: }
17: }
18: }
19:
20: class B{
21: static void DoThis(){
22: A.X = 1;
23: }
24: }
25: }
26:
27: namespace NameSpace2{
28: internal class C{
29:
30: public static int W;
31:
32: static void DoThis(){
33: NameSpace1.A.X = 1;
34: }
35: }
36: }
This program compiles properly. Remember to compile with the /target: library option if you are using csc.exe since there is no Main() method:
c:expt>csc /target:library Source1.cs
In this program, the accessibility of the field X in class A of the NameSpace1 namespace (declared on line 5) is being tested on line 33.
The program shows that NameSpace1.A.X is accessible from:
within the same class (line 10);
a nested class of the same class (line 15);
another class of the same namespace in the same source file (line 22);
another class of a different namespace in the same source file (line 33).
In fact, X is accessible from anywhere inside the same program (codes in the same source file). However, X is not accessible from another class defined in a separate source file regardless of whether that class is in the same namespace as A. The following program, Source2.cs, written in another source file demonstrates this. Remember to compile Source2.cs using the /reference option if you are using csc.exe so that it can find the classes you have just written in Source1.dll:
c:expt>csc /reference:Source1.dll /target:library Source2.cs
1: // Source2.cs
2:
3: using NameSpace1;
4: using NameSpace2;
5:
6: // default namespace
7: class D:A{
8: static void DoThis() {
9: A.X = 1; // compilation error
10: }
11: }
12:
13: namespace NameSpace1 {
14: class E{
15: static void DoThis() {
16: A.X = 1; // compilation error
17: }
18: }
19: }
Compilation error:
Source2.cs(9,5): error CS0122: 'NameSpace1.A.X' is inaccessible due to its protection level Source2.cs(16,7): error CS0122: 'NameSpace1.A.X' is inaccessible due to its protection level
NameSpace1.A.X is only accessible to code written in Source1.cs only. Even a class in the same namespace (class E in Source2.cs) cannot access it if it is in another program (source file).
Having understood internal accessibility, let's try out protected internal. Line 6 of Source1.cs declares field Y as protected internal. This time, Y is accessible to a class in an external program which is a subclass of NameSpace1.A. I have modified Source2.cs to prove this point:
1: // Source2.cs 2: 3: using NameSpace1; 4: 5: namespace NameSpace3 { 6: class D:A{ // subclass 7: static void DoThis() { 8: A.Y = 1; // ok 9: } 10: } 11: class E{ // non-subclass 12: static void DoThis() { 13: A.Y = 1; // compilation error 14: } 15: } 16: }
Compilation error:
Source2.cs(13,7): error CS0122: 'NameSpace1.A.Y' is inaccessible due to its protection level
Here, A.Y is accessible by a class in another program (source file) as long as that class is a subclass of NameSpace1.A.
As a final note, notice that although both fields NameSpace1.A.Z and NameSpace2.C.W in Source1.cs (declared on lines 7 and 30 respectively) have been declared as public, their resultant accessibility is different because class A is a public class, while class C is an internal class.
Because class C is internal, you cannot access the class from another program. So despite C.W being declared as public, it is inaccessible from a class written in, say, Source2.cs. On the other hand, A.Z is truly free for all to use.
18.227.102.162