Microsoft.NET

……………………………………………….Expertise in .NET Technologies

Access Modifiers in C# (OOP’s) – Part 4

Posted by Ravi Varma Thumati on July 13, 2009

Access Modifiers in C#

All types and type members have an accessibility level, which controls whether they can be used from other code in your assembly or other assemblies. You specify the accessibility of a type or member when you declare it by using one of these access modifiers:

  • public:

The type or member can be accessed by any other code in the same assembly or another assembly that references it.

  • private

The type or member can only be accessed by code in the same class or struct.

  • protected

The type or member can only be accessed by code in the same class or struct, or in a derived class.

  • internal

The type or member can be accessed by any code in the same assembly, but not from another assembly.

Public (C# Reference)

The public keyword is an access modifier for types and type members. Public access is the most permissive access level. There are no restrictions on accessing public members, as in this example:

class SampleClass
{
    public int x; // No access restrictions.
}

Example

In the following example, two classes are declared, Point and MainClass. The public members x and y of Point are accessed directly from MainClass.

C#

class PointTest
{
    public int x;
    public int y;
}
class MainClass4
{
    static void Main()
    {
        PointTest p = new PointTest();
        // Direct access to public members:
        p.x = 10;
        p.y = 15;
        Console.WriteLine("x = {0}, y = {1}", p.x, p.y);
    }
}
// Output: x = 10, y = 15

If you change the public access level to private or protected, you will get the error message:

‘Point.y’ is inaccessible due to its protection level.

Private (C# Reference)

The private keyword is a member access modifier. Private access is the least permissive access level. Private members are accessible only within the body of the class or the struct in which they are declared, as in this example:

class Employee
{
    private int i;
    double d;   // private access by default
}

Nested types in the same body can also access those private members.

It is a compile-time error to reference a private member outside the class or the struct in which it is declared.

Example

In this example, the Employee class contains two private data members, name and salary. As private members, they cannot be accessed except by member methods. Public methods named GetName and Salary are added to allow controlled access to the private members. The name member is accessed by way of a public method, and the salary member is accessed by way of a public read-only property.

C#

class Employee2
{
    private string name = "FirstName, LastName";
    private double salary = 100.0;

    public string GetName()
    {
        return name;
    }

    public double Salary
    {
        get { return salary; }
    }
}
class PrivateTest
{
    static void Main()
    {
        Employee2 e = new Employee2();

        // The data members are inaccessible (private), so
        // they can't be accessed like this:
        //    string n = e.name;
        //    double s = e.salary;

        // 'name' is indirectly accessed via method:
        string n = e.GetName();

        // 'salary' is indirectly accessed via property
        double s = e.Salary;
    }
}

Protected (C# Reference)

The protected keyword is a member access modifier. A protected member is accessible within its class and by derived class instances. For a comparison of protected with the other access modifiers,

Example

A protected member of a base class is accessible in a derived class only if the access occurs through the derived class type. For example, consider the following code segment:

C#

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;
    }
}

The statement a.x = 10 generates an error because it is made within the static method Main, and not an instance of class B.

Struct members cannot be protected because the struct cannot be inherited.

In this example, the class DerivedPoint is derived from Point. Therefore, you can access the protected members of the base class directly from the derived class.

C#

class Point
{
    protected int x;
    protected int y;
}
class DerivedPoint: Point
{
    static void Main()
    {
        DerivedPoint dpoint = new DerivedPoint();

        // Direct access to protected members:
        dpoint.x = 10;
        dpoint.y = 15;
        Console.WriteLine("x = {0}, y = {1}", dpoint.x, dpoint.y);
    }
}
// Output: x = 10, y = 15

If you change the access levels of x and y to private, the compiler will issue the error messages:

‘Point.y’ is inaccessible due to its protection level.

‘Point.x’ is inaccessible due to its protection level.

Internal (C# Reference)

The internal keyword is an access modifier for types and type members. Internal types or members are accessible only within files in the same assembly, as in this example:

public class BaseClass
{
    // Only accessible within the same assembly
    internal static int x = 0;
}

A common use of internal access is in component-based development because it enables a group of components to cooperate in a private manner without being exposed to the rest of the application code. For example, a framework for building graphical user interfaces could provide Control and Form classes that cooperate by using members with internal access. Since these members are internal, they are not exposed to code that is using the framework.

It is an error to reference a type or a member with internal access outside the assembly within which it was defined.

Note:
An internal virtual method can be overridden in some languages, such as textual Microsoft intermediate language (MSIL) using Ilasm.exe, even though it cannot be overridden by using C#.

Example

This example contains two files, Assembly1.cs and Assembly1_a.cs. The first file contains an internal base class, BaseClass. In the second file, an attempt to instantiate BaseClass will produce an error.

// Assembly1.cs
// Compile with: /target:library
internal class BaseClass
{
   public static int intM = 0;
}
// Assembly1_a.cs
// Compile with: /reference:Assembly1.dll
class TestAccess
{
   static void Main()
   {
      BaseClass myBase = new BaseClass();   // CS0122
   }
}

In this example, use the same files you used in example 1, and change the accessibility level of BaseClass to public. Also change the accessibility level of the member IntM to internal. In this case, you can instantiate the class, but you cannot access the internal member.

// Assembly2.cs
// Compile with: /target:library
public class BaseClass
{
   internal static int intM = 0;
}
// Assembly2_a.cs
// Compile with: /reference:Assembly1.dll
public class TestAccess
{
   static void Main()
   {
      BaseClass myBase = new BaseClass();   // Ok.
      BaseClass.intM = 444;    // CS0117
   }
}

Protected internal

The type or member can be accessed by any code in the same assembly, or by any derived class in another assembly.

The following examples demonstrate how to specify access modifiers on a type and member:

C#

public class Bicycle
{
    public void Pedal() { }
}

Not all access modifiers can be used by all types or members in all contexts, and in some cases the accessibility of a type member is constrained by the accessibility of its containing type. The following sections provide more details about accessibility.

Class and Struct Accessibility

Classes and structs that are declared directly within a namespace (in other words, they are not nested within other classes or structs) can be either public or internal. Internal is the default if no access modifier is specified. Nested classes and structs may also be declared as private. Private nested types are not accessible from the containing type.

Derived classes cannot have greater accessibility than their base types. In other words, you cannot have a public class B that derives from an internal class A. If this were allowed, it would have the effect of making A public, because all protected or internal members of A are accessible from the derived class.

You can enable specific other assemblies to access your internal types by using the InternalsVisibleToAttribute. .

Class and Struct Member Accessibility

Class members (including nested classes and structs) can be declared with any of the five types of access. Struct members cannot be declared as protected because structs do not support inheritance.

The accessibility of a member can never be greater than the accessibility of its containing type. For example, a public method declared in an internal type has only internal accessibility.

When a member of a class or struct is a property, field, method, event, or delegate, and that member either is a type or has a type as a parameter or return value, the accessibility of the member cannot be greater than the type. For example, you cannot have a public method M that returns a class C unless C is also public. Likewise, you cannot have a protected property of type A if A is declared as private.

User-defined operators must always be declared as public.

Destructors cannot have accessibility modifiers.

To set the access level for a class or struct member, add the appropriate keyword to the member declaration. Here are some examples:

C#

// public class:
public class Tricycle
{
    // protected method:
    protected void Pedal() { }

    // private field:
    private int wheels = 3;

    // protected internal property:
    protected internal int Wheels
    {
        get { return wheels; }
    }
}

Note:
The protected internal accessibility means protected OR internal, not protected AND internal. In other words, a protected internal member is accessible from any class in the same assembly, including derived classes. To limit accessibility to only derived classes in the same assembly, declare the class itself internal, and declare its members as protected.

Other Types

Interfaces declared directly with a namespace can be declared as public or internal and like classes and structs, interfaces default to internal access. Interface members are always public because the purpose of an interface is to enable other types to access a class or struct. No access modifiers can be applied to interface members.

Key Points to Remember:

  • The default access modifier for the classes is internal, and the default access modifier for the members is private.
  • Struts members can not be declared protected, or protected internal because it is not support the inheritance.
  • Destructors can not take any access modifiers.
  • Constructors must be public.
  • Enumeration is public.
  • Only one access modifier is allowed for a member except when using the protected internal access modifier.
  • Namespace doesn’t take any access modifier, because it has no any restriction.
  • By default, delegates have internal access.

A quick description of access modifiers with a diagram showing accessibility limits

C# Accessibility

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: