To promote encapsulation, a type or type member may limit its accessibility to other types and other assemblies by adding one of five access modifiers to the declaration:
public
Fully accessible. The implicit accessibility for members of an enum or interface.
internal
Accessible only within containing assembly or friend assemblies. The default accessibility for nonnested types.
private
Visible only within containing type. The default accessibility members of a class or struct.
protected
protected internal
The union of protected
and
internal
accessibility. (This is
less restrictive than protected
or internal
alone.)
The CLR has the concept of the intersection of protected and internal accessibility, but C# does not support this.
Class2
is accessible from outside its assembly;
Class1
is not:
class Class1 { } // Class1 is internal (default)
public
class Class2 { }
ClassB
exposes field x
to other types in the same assembly; ClassA
does not:
class ClassA { int x; } // x is private
// (default)
class ClassB { internal
int x; }
Functions within Subclass
can call Bar
but not Foo
:
class BaseClass
{
void Foo() { } // Foo is private (default)
protected
void Bar() { }
}
class Subclass : BaseClass
{
void Test1() { Foo(); } // Error: cannot access Foo
void Test2() { Bar(); } // OK
}
A type caps the accessibility of its declared members. The most common example of
capping is when you have an internal
type with public
members. For example:
class C { public void Foo() {} }
C’s (default) internal
accessibility caps Foo's
accessibility, effectively making Foo internal
. The reason Foo
would be marked public
is to make for
easier refactoring, should C
later be changed to
public
.
When overriding a base class function, accessibility must be identical on the overridden function.
The compiler also prevents any inconsistent use of access modifiers. For example, a subclass itself can be less accessible than a base class, but not more accessible:
internal
class A { }public
class B : A { } // Error