Access Modifiers
Modifiers control the access levels for members.
Non-nested Types
Type | Default | Allowed |
---|---|---|
namespace | public | public |
enum | public | public |
interface | internal | public, internal |
class | internal | public, internal |
struct | internal | public, internal |
delegate | internal | public, internal |
Nested and Member Accessibility
Type | Default | Allowed |
---|---|---|
namespace | public | public |
enum | public | public |
interface | public | none |
class | private | public, protected, internal, private, protected internal |
struct | private | public, internal, private |
delegate | private | public, protected, internal, private, protected internal |
constructor | private | public, protected, internal, private, protected internal |
interface member | public | none |
method | private | public, protected, internal, private, protected internal |
field | private | public, protected, internal, private, protected internal |
user-defined operator | none | public |
Structs cannot inherit from structs or classes (although they can from interfaces), hence protected is not a valid modifier.
public
Fully accessible. There is no restrictions on accessing public members of a type. This is the most permissive level access. Implicit for enum and interface members.
class TestClass { public int x; }
private
Is only a member access modifier, which means it cannot be access outside the class. Default accessibility for members or struct.
class Employee { private int i; double d; // private access by default }
protected
With protected member is accessible within its class and derived class.
protected internal
private protected
class A { protected int x = 123; } class B : A { static void Main() { A a = new A(); B b = new B(); // Error CS1540, because x can only be accessed by // classes derived from A. // a.x = 10; // OK, because this class derives from A. b.x = 10; } }
internal
Only accessible from within the files in the same assembly or friend assemblies. Useful for component based development. Default for non-nested types.
public class BaseClass { // Only accessible within the same assembly internal static int x = 0; }
protected internal
A protected internal member of a base class is accessible from any type within its containing assembly. It is also accessible in a derived class located in another assembly only if the access occurs through a variable of the derived class type.
private protected
A private protected member of a base class is accessible from derived types in its containing assembly only if the static type of the variable is the derived class type.
Friend Assemblies
You can expose internal members to other friend assemblies by adding the System.Runtime.CompilerServices.InternalsVisibleTo assembly attribute. If the friend assembly has a strong name you must specify its full 160-byte public key.
// Unsigned friend: // [assembly: InternalsVisibleTo ("Friend")] // Signed friend: // [assembly: InternalsVisibleTo ("StrongFriend, PublicKey=0024f000048c...")]
Accessibility Capping
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.
// A type caps the accessibility of its declared members: class C // Class C is implicitly internal { public void Foo() {} // Foo's accessibility is capped at internal } static void Main() { }
Restrictions on Access Modifiers
Overriding base class methods must be identical on the overridden function except overriding protected internal method in another assembly. The compiler prevents inconsistent use of access modifiers.
class BaseClass { protected virtual void Foo() {} } class Subclass1 : BaseClass { protected override void Foo() {} } // OK class Subclass2 : BaseClass { public override void Foo() {} } // Error // A subclass itself can be less accessible than a base class, but not more: internal class A { } public class B : A { } // Error static void Main() { }