Recipe3.15.Determining a Variable s Type with the is Operator
 C# Cookbook Authors: Hilyard J.,  Teilhet S. Published year: 2004 Pages: 86/424

### Recipe 3.15. Determining a Variable's Type with the is Operator

#### Problem

A method exists that creates an object from one of several types of classes. This object is then returned as a generic object type. Based on the type of object that was initially created in the method, you want to branch to different logic.

#### Solution

Use the is operator. This operator returns a Boolean true or false indicating whether the cast is legal, but the cast never actually occurs.

Suppose you have four different point classes:

```public class Point2D {…}
public class Point3D {…}
public class ExPoint2D : Point2D {…}
public class ExPoint3D : Point3D {…}
```

Next, you have a method that accepts an integer value and, based on this value, one of the four specific point types is returned:

```public object CreatePoint(PointTypeEnum pointType)
{
switch (pointType)
{
case PointTypeEnum.Point2D:
return (new Point2D( ));
case PointTypeEnum.Point3D:
return (new Point3D( ));
case PointTypeEnum.ExPoint2D:
return (new ExPoint2D( ));
case PointTypeEnum.ExPoint3D:
return (new ExPoint3D( ));
default:
return (null);
}
}
```

where the PointTypeEnum is defined as:

```public enum PointTypeEnum
{
Point2D, Point3D, ExPoint2D, ExPoint3D
}
```

Finally, you have a method that calls the CreatePoint method. This method handles the point object type returned from the CreatePoint method based on the actual point object returned:

```public void CreateAndHandlePoint( )
{
// Create a new point object and return it.
object retObj = CreatePoint(PointTypeEnum.Point2D);

// Handle the point object based on its actual type.
if (retObj is ExPoint2D)
{
Console.WriteLine("Use the ExPoint2D type");
}
else if (retObj is ExPoint3D)
{
Console.WriteLine("Use the ExPoint3D type");
}
else if (retObj is Point2D)
{
Console.WriteLine("Use the Point2D type");
}
else if (retObj is Point3D)
{
Console.WriteLine("Use the Point3D type");
}
else
{
Console.WriteLine("Invalid point type");
}
}
```

Notice that the tests for the ExPoint2D and ExPoint3D objects are performed before the tests for Point2D and Point3D . This order will allow you to differentiate between base classes and their derived classes ( ExPoint2D derives from Point2D and ExPoint3D derives from Point3D ). If you had reversed these tests, the test for Point2D would evaluate to TRue for both the Point2D class and its derivatives ( ExPoint2D ).

#### Discussion

The is operator is a fast and easy method of predetermining whether a cast will work. If the cast fails, you have saved yourself the overhead of trying the cast and handling a thrown exception. If the is operator determines that this cast can successfully be performed, all you need to do is perform the cast.

The is operator is defined as follows :

```
expression

is

type

```

The expression and type are defined as follows:

expression

A reference type

type

The type to which to cast the reference type defined by expression

This expression returns a Boolean value: TRue if the cast will succeed or false if the cast will fail. For example:

```if (SpecificObj is Base)
{
// It is of type Base.
}
else
{
// Cannot cast SpecificObj to a Base type object.
}
```

 Never use the is operator with a user -defined conversion (either explicit or implicit). The is operator always returns false when used with these types of conversions, regardless of whether the cast can be performed.

This operator does not work with user-defined conversions (both explicit and implicit). Unlike the as operator, a compile-time error will not be displayed; instead, the is operator will always return false . This operator should never be used with user-defined conversions, since the result will always be in question. Also, unlike the as operator, the is operator will work with unboxing conversions.

The following code determines whether an unboxing operation can be performed:

```// An int is passed in to this method and boxed.
public void SomeMethod(object o)
{
if (o is int)
{
// o can be unboxed.
// It is now possible to cast o to an int.
int x = (int)o;
}
else
{
// Cannot unbox o.
}
}
```

This code first declares an integer variable x and boxes it into an object variable o . The is operator is then used to determine whether o can be unboxed back into the integer variable x . This is the one case in which it is absolutely necessary to use is if you want to avoid an exception. You can't use as here because there is no such thing as a null int , so it cannot tell you if the unboxing fails.