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