Wednesday 27 December 2017

Access Modifiers

Access specifiers are keywords used to specify the declared accessibility of a member or a type.

Why to use access modifiers?
Access modifiers are an integral part of object-oriented programming. They support the concept of encapsulation, which promotes the idea of hiding functionality. Access modifiers allow you to define who does or doesn't have access to certain features.

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

There are four access modifiers:
  • public
  • protected
  • internal
  • private
The following six accessibility levels can be specified using the access modifiers:
  • public: Access is not restricted.
  • protected: Access is limited to the containing class or types derived from the containing class.
  • internal: Access is limited to the current assembly.
  • protected internal: Access is limited to the current assembly or types derived from the containing class.
  • private: Access is limited to the containing type.
  • private protected: Access is limited to the containing class or types derived from the containing class within the current assembly.


public

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.

Accessibility:
  • Can be accessed by objects of the class.
  • Can be accessed by derived classes.
Example:
In the following example, two classes are declared, TestClass and MainClass. The public members x and y of TestClass are accessed directly from MainClass.

Class TestClass
{
       public int x;
       public int y;
}

Class MainClass
{
      static void Main()
      {
           TestClass t = new TestClass();
           t.x = 15;
           t.y = 25;  //Direct access to public members.
           Console.WriteLine("x = {0}, y = {1}", p.x, p.y);
      }
}

Output : x = 15; y = 25;

If you change the public access level to private or protected, you will get the error message: 'TestClass.y' is inaccessible due to its protection level.


protected

A protected member is accessible within its class and by derived class instances.
A protected member of a base class is accessible in a derived class only if the access takes place through the derived class type.

Accessibility:
  • Cannot be access by object.
  • By derived classes.
Example:
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.

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 = 15;
           dpoint.y = 25;
           Console.WriteLine("x = {0}, y = {1}", dpoint.x, dpoint.y);

           Point p = new Point();
           p.x = 15; //Error CS1540, because x can only be accessed
                          //by classes derived from Point.
      }
}

Output: x = 15, y = 25

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

'Point.x' is inaccessible due to its protection level.
'Point.y' is inaccessible due to its protection level.

The statement p.x = 15 generates an error because it is made within the static method Main, and not an instance of class DerivedPoint.

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


private

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.
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.

Accessibility:
  • Cannot be accessed by object.
  • Cannot be accessed by derived classes.
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.

class Employee
{
    private string name = "FName, LName";
    private double salary = 200.0;

    public string GetName()
    {
        return name;
    }

    public double Salary
    {
        get { return salary; }
    }
}

class PrivateTest
{
    static void Main()
    {
        Employee e = new Employee();

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


internal

The internal keyword is an access modifier for types and type members. We can declare a class as internal or its member as internal. Internal members are accessible only within files in the same assembly (.dll).
In other words, access is limited exclusively to classes defined within the current project assembly.

Accessibility:
In same assembly (public)
  • Can be accessed by objects of the class.
  • Can be accessed by derived classes.

In other assembly (internal)
  • Cannot be accessed by object.
  • Cannot be accessed by derived classes.

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.

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

Example:
In this example, use the same files 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  
   }  
}  

Saturday 23 December 2017

Nullable Types


  • Nullable types represent value-type variables that can be assigned the value of null.
  • You cannot create a nullable type based on a reference type. (Reference type already support the n ull value.)
  • The syntax T? is shorthand for Nullable<T>, where T is a value type. The two forms are interchangeable.
  • Assign a value to a nullable type just as you would for an ordinary value type.
    eg:- int?X = 10; OR double?D = 4.190.
  • A nullable type can also be assigned the value null.
    eg:- int?X = null.
  • Use the Nullable<T>.GetValueOrDefault method to return either the assigned value, or the default value for the underlying type if the value is null.
    eg:- int?X = 10;
            int J = X.GetValueOrDefault();
  • Use the Hashvalue and Value read-only properties to test for null and retrieve the value.
    eg:- if(X.Hashvalue)J = X.Value;

    - The Hashvalue property returns true if the variable contains a value, or false if it is null.
    - The value property returns a value if one is assigned. Otherwise, a system.InvalidOperationException is thrown.
    - The default value for Hashvalue is false. The value property has no default value.
  • You can also use the '==' and '!=' operators with nullable type.
    eg:- if(X!=null)Y=X;
  • Use the '??' operator to assign a default value that will be applied when a nullable type whose current value is 'null' is assigned to a non-nullable type.
    eg:- int?X = null';
           int Y = X ?? -1;
  • Nested nullable types are not allowed. The following line will not compile:
    Nullable<Nullable<T>>n;

Anonymous Types


  • Anonymous types are class types that derive directly from object, and that cannot be cast to any type except object.
  • The compiler provides a name for each anonymous type, although your application cannot access it.
  • You cannot declare a field, a property, an event, or the return type of a method as having an anonymous type.
  • You cannot declare a formal parameter of a method, property, constructor, or indexer as having an anonymous type.
  • To pass an anonymous type, or a collection that contains anonymous type, as an argument to a method, you can declare the parameter as type object.
  • Two instances of the same anonymous type are equal only if all their properties are equal.
  • anonymous types typically used in the 'Select' clause of a query expression to return a subset of properties from each object in the source sequence.
    eg:- LINQ Query expression.
    var anonymousData = from pl in data select new {pl.Fname, pl.Lname};
  • Anonymous type contain one or more public read-only properties.
  • We can create anonymous types by using 'new' keyword together with the object initializer.
    eg:- var anonymousData = new {Fname="Vivek", Lname="Sharma"};
  • Anonymous type is a way to define read-only properties into a single object without having to define type explicitly.
  • Anonymous type throws compile time errors.

Different type of conversions


  1.  Implicit Conversions:
    - No special syntax is required because the conversion is type safe and no data will be lost.
    - eg: Conversion from smaller to larger integral types, and conversion from derived classes to base classes.
  2.  Explicit Conversions (Casts):
    - Explicit conversion requires a cast operator.
    - Casting is required when information might be lost in the conversion, or when the conversion might not succeed for other reasons.
    - eg: Numeric conversion to a type that has less precision or a small range, and conversion of a base class instance to a derived class.
  3.  User-defined Conversions:
    - Performed by special methods that you can define to enable explicit and implicit conversions between custom types that do not have a base class- derived class relationship.
  4.  Conversion with helper classes:
    - To convert between non-compatible types, such as integers and system datetime objects, or hexadecimal strings and byte arrays, you can use the system.bitconverter class, the system.convert class, and the parse method of the built-in numeric types, such as Int32.Parse.