Monday, June 21, 2010

Access Modifiers in C#


All types and type members have an accessibility level, which controls whether they can be used from other code in our assembly or other assemblies.

    In C# there are 5 different types of Access Modifiers. You can use any of the 5 access modifiers to specify the accessibility of a type or member when you declare it:

1) public: 
     The type or member can be accessed by any other code in the same
     assembly or another assembly that references it. 
 2) private: 
     The type or member can only be accessed by code in the same class or struct. 
3) protected
     The type or member can only be accessed by code in the same class or
        struct, or in a derived class.  
4) internal: 
     The type or member can be accessed by any code in the same assembly,
        but not from another assembly.
5) 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:

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.

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 outside 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.
i.e. if you write following in a namespace it will not compile

namespace ConsoleApplication1
{

 internal class A
    {
        int i = 0;
    }

    public class B:A
    {
        int i = 0;
    }

 }
Here is an essence of error that flashed by compiler "Inconsistent accessibility: base class A is less accessible than class B  "

  You can enable specific other assemblies to access your internal types by using the InternalsVisibleToAttribute.
 Here we need to add line below on one of to the assembly
 [assembly:InternalsVisibleToAttribute("OtherAssemblyName")]
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:
One 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.

Point To Remember:
 1) User-defined operators must always be declared as public. 
 2) Destructors cannot have accessibility modifiers.

Example of using Access Modifier:

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

}

    Interfaces declared directly within 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.
   Enumeration members are always public, and no access modifiers can be applied to enumeration members.
By default, delegates have internal access.

Note:
1) Access modifier cannot be used for all types e.g. one need not specify the access modifier for interface member, enumeration members & destructor.

2) One cannot use any other access modifier to interface other than internal or public .so interface can never get private access modifier.
 Default Access Modifiers:

  When we create a type or type members without assigning any access modifier it get the default access modifier specific to that context.

  When we define a data type of some kind (class, struct, enum, etc.) but do not specify an access modifier, it will get default access modifier to be internal.

    If we doesn’t specify access modifier for type members (e.g class or structure variable, methods) then by default become private.
  Default Access modifier for interface is internal.

References:http://www.davidarno.org/c-howtos/friend-assemblies-accessing-internal-classes-externally/ 

No comments:

Post a Comment