Tuesday, April 29, 2014

Is and As Keyword , type casting

IS and AS keyword in C#

Implicit casts

Let us start by looking into the conversions that are done automatically by C#. Implicit casts are the casts that does not require the programmer to do an explicit conversion. One data type can simply be assigned to another. There are some rules that govern the implicit cast.

Built-in numeric types, widening conversions.

Reference types, Derived class to base class.

The built in numeric types can be assigned to each other if a narrow type is being assigned to wider type. This is possible because the compiler know that the only problem in such operations is that a little more memory will be needed to hold this type and no data will be truncated or lost. So the following conversion will not need any explicit cast.

 Collapse | Copy Code
int i = 10;
long l = i;

Secondly, If we try to assign a value from derived class to a base class it will work. that is because a derived class always is-a base class. Also, from a memory perspective a base class variable pointing to a derived class object can safely access the base class part of the object in memory without any problem. SO following code will work without needing any explicit casts.

 Collapse | Copy Code
class Base
{

}

class Derived : Base
{

}  

class Program
{
    static void Main(string[] args)
    {
        Derived d = new Derived();
        Base b = d;     
    }
}
Other then these two possible scenarios, all the conversions will create compile time errors. Still, If we need to perform the conversions, we will have to use explicit casting/conversion.

Explicit casts

If we find ourselves in need of conversion that is either narrowing conversion or conversion between unrelated types then we will have to use explicit conversions. Using explicit conversions we are actually letting the compiler know that we know there is possible information loss but still we need to make this conversion. So if we need to convert a long type to an integer type we need to cast it explicitly.

 Collapse | Copy Code
long l = 10;
int i = (int)l;
On similar lines, if we need to cast a base class to a derived class I will have to cast it explicitly.

 Collapse | Copy Code
Base b = new Base();
Derived d = (Derived)b;

Explicit casting actually tells the compiler that we know about possible information loss/mismatch but still we need to perform this cast. This is ok for inbuilt numeric types
but in case of reference types, there is a possibility that the types are not at all compatible i.e. casting from one type to another is not at all possible.


 (Downcasting , Pointing Base class object  memory block heap by child class reference pointer . (converting generalize to more specialize ) )
Base b = new Base();
Derived d = (Derived)b;

Above code will not throw any compile time error but at runtime you will get the Invalid type Exception. Why How can reference pointer of child class find its own property in the Base class object In this way that is called Incomplete Object.


For example casting a string "abc" to Integer is not possible.

Such casting expressions will compile successfully but they will fail at run-time. What C# compiler does it that it checks whether these two types are cast compatible or not and if not it raises an exception InvalidCastException.

'is' and 'as' operators

So whenever we are using explicit casts, it is always a good idea to wrap the cast inside a try-catch block. C# also provides is and as operators which are helpful in performing explicit casts in an exception safe manner.






Introduction

Type casting is one of the unavoidable things in software development. In many situations we need to convert one object (Type) to another object (Type) and some times we get an exception like this: "Cannot implicitly convert type 'Object one' to 'object two'". To avoid this type of exceptions and check object compatibility, C# provides two operators namely is and as.
is operator
The is operator in C# is used to check the object type and it returns a bool value: true if the object is the same type and false if not.

For null objects, it returns false.


Syntax:
bool isobject = (Object is Type);
Example:
namespace IsAndAsOperators
{
    // Sample Student Class
    class Student
    {
        public int stuNo { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }

    }
    // Sample Employee Class
    class Employee
    {
        public int EmpNo { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public double Salary { get; set; }

    }
    class Program
    {

        static void Main(string[] args)
        {
            Student stuObj = new Student();
            stuObj.stuNo = 1;
            stuObj.Name = "Siva";
            stuObj.Age = 15;

            Employee EMPobj=new Employee();
            EMPobj.EmpNo=20;
            EMPobj.Name="Rajesh";
            EMPobj.Salary=100000;
            EMPobj.Age=25;

            // Is operator

            // Check Employee EMPobj is Student Type

            bool isStudent = (EMPobj is Student);
            System.Console.WriteLine("Empobj is a Student ?: {0}", isStudent.ToString());

            // Check Student stiObj is Student Typoe
            isStudent = (stuObj is Student);
            System.Console.WriteLine("Stuobj is a Student ?: {0}", isStudent.ToString());

            stuObj = null;
            // Check  null object Type
            isStudent = (stuObj is Student);
            System.Console.WriteLine("Stuobj(null) is a Student ?: {0}", isStudent.ToString());
            System.Console.ReadLine();
        }
    }
Output
Empobj is a Student ?: False
Stuobj is a Student ?: True
Stuobj(null) is a Student ?: False
as operator
The as operator does the same job of is operator but the difference is instead of bool, it returns the object if they are compatible to that type, else it returns null.
Syntax:
Type obj = Object as Type;
Example:
namespace IsAndAsOperators
{
    // Sample Student Class
    class Student
    {
        public int stuNo { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }

    }
    // Sample Employee Class
    class Employee
    {
        public int EmpNo { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public double Salary { get; set; }

    }
    class Program
    {
        static void Main(string[] args)
        {
            Student stuObj = new Student();
            stuObj.stuNo = 1;
            stuObj.Name = "Praveen";
            stuObj.Age = 15;

            Employee EMPobj=new Employee();
            EMPobj.EmpNo=20;
            EMPobj.Name="Rajesh";
            EMPobj.Salary=100000;
            EMPobj.Age=25;    

            System.Console.WriteLine("Empobj is a Student ?: {0}", CheckAndConvertobject(EMPobj));

            System.Console.WriteLine("StuObj is a Student ?: {0}", CheckAndConvertobject(stuObj));
            System.Console.ReadLine();

        }

        public static string CheckAndConvertobject(dynamic obj)
        {
           // If obj is Type student it asign value to Stuobj else it asign null
            Student stuobj = obj as Student;
            if (stuobj != null)
                return "This is a Student and his name is " + stuobj.Name;

                return "Not a Student";        


        }
    }  
}
Output:
Empobj is a Student ?: Not a Student
StuObj is a Student ?: This is a Student and his name is Praveen
Advantage of 'as' over 'is
In the case of is operator, to type cast, we need to do two steps:
1.     Check the Type using is
2.     If it’s true then Type cast
Actually this affects the performance since each and every time the CLR will walk the inheritance hierarchy, checking each base type against the specified type. To avoid this, use as it will do it in one step. Only for checking the type should we use the is operator.

namespace KudVenkatCsharp6
{
    class Person
    { public virtual void showname() { } }
    class employee:Person
    { public override void showname() { Console.WriteLine("employee name"); } }
    class student : Person { public void Move() { Console.WriteLine("Student moves"); } }
    class Programs
    {
        public static void Main()
        {
            Person p = new Person();
            employee e = new employee();
            student s = new student();
            if (p is Person)
            {
                Console.WriteLine("p is Person");
            }
            else
            {
                Console.WriteLine("p is not Person");
            }
            if (e is student)
            {
                Console.WriteLine("employee is student");
            }
            else
            {
                Console.WriteLine("employee is not student");
            }
            //student s2 = s as Person;//Error  2      Cannot implicitly convert type 'KudVenkatCsharp6.Person' to 'KudVenkatCsharp6.student'. An explicit conversion exists (are you missing a cast?) So I did explicit cast below like

           // student s3 = (student)p;

            //But above will certainly give Runtime exception To handel these situation first we can check with these op
            /*
             *  (Downcasting , Pointing Base class object  memory block heap by child class reference pointer . (converting generalize to more specialize ) )
Base b = new Base();
Derived d = (Derived)b;

Above code will not throw any compile time error but at runtime you will get the Invalid type Exception. Why How can reference pointer of child class find its own property in the Base class object In this way that is called Incomplete Object.

             */
          //  student s1 =((student)(s as Person));
            student s1 = ((student)(s as Person));
            if (s1!=null)
            {
                s1.Move();
                Console.WriteLine("Valid type");
            }
            else
            {
                Console.WriteLine("Not valid type");
            }
            Person p1 = e as Person;
            if (p1 !=null)
            {
                p1.showname();
            }
            else
            {
                Console.WriteLine("Not valid type");
            }
            Console.ReadLine();
        }
    
    }
}
Output
p is Person
employee is not studen
Student moves
Valid type

employee name

No comments:

Post a Comment