Run-time type information. Statements is, as. Examples

Run-time type information. Statements is, as. Examples


Contents



1. What is the run-time type information (RTTI)? Advantages of using

In some cases, when writing programs, you need to determine the type of data during program execution. This means that at the time of compilation it is not known what type this or that data will have. To define a type in C#, an appropriate mechanism has been developed, which is called run-time (dynamic) type identification.

Runtime type identification is effective in the following cases:

  • if the classes inherit each other or form a hierarchy, then if there is a reference to the base class, you can determine the type of the object by this reference (see item 5);
  • if it is necessary to determine the result of a casting operation in order to avoid generating an exceptional situation in case of an erroneous casting;
  • runtime type identification is effectively used in reflection. More details about reflection is described here.

   

2. What keywords (operators) are introduced in C# to provide runtime type identification?

To provide dynamic identification of types in the C# language, three operators are introduced:

  • operator is – checks if the type of the expression matches the specified data type;
  • operator as – designed to avoid the occurrence of an exceptional situation in case of unsuccessful type conversion;
  • оператор typeof – used to obtain information about a given type (class). More on the typeof operator is described here.

   

3. The general form of operator is

The general form of the is operator is as follows:

expression is type

here

  • expression have the designation of an expression that describes an object;
  • type is a type with which the type of expression is compared. If the expression and type have the same data type, then the result of the operation will be true. Otherwise, the result of the is operation will be false.

Most often, the is operator is used in the condition of the if statement. In this case, the general form of the if statement with the is operator is as follows

if (expression is type)
{
    // operations that need to be performed if the types match
    // ...
}
else
{
    // operations that need to be performed if the types do not match
    // ...
}

   

4. Examples of using the is operator for basic types and expressions

Example 1. A snippet of code demonstrating the use of the is operator for variables of basic types int, float.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp5
{
    class Program
    {
        static void Main(string[] args)
        {
            // runtime type information
            int a, b;
            float x;

            // variables must be initialized before use
            a = 25;
            b = 33;
            x = 3.9f;

            // check if there is 'a' of type int
            if (a is int)
                Console.WriteLine("Variable a is of type int.");
            else
                Console.WriteLine("Variable a is not of type int");

            // check if there is a variable b of type float
            if (b is float)
                Console.WriteLine("Variable b is of type float");
            else
                Console.WriteLine("Variable b is not of type float");

            // check if there is a variable x of type double
            if (x is double)
                Console.WriteLine("Variable x is of type double");
            else
                Console.WriteLine("Variable x is not of type double");
        }
    }
}

As can be seen from the above example, in order to use the is operator, the expression may have some value. If at the beginning of the Main() function, remove the assignment lines of the variables a, b, x

...
a = 25;
b = 33;
x = 3.9f;
...

the compiler will generate an error like

Use of unassigned local variable a
Use of unassigned local variable b
Use of unassigned local variable x

Example 2. The code snippet shows how to use the is operator to determine the type of a calculated expression.

// dynamic type identification
// definition of expression type
float x;

// variables must be initialized before use
x = 3.9f;

// check if the expression of type double
if ((2.5 + x) is double)
    Console.WriteLine("The expression is of type double");
else
    Console.WriteLine("The expression does not have type double ");
// Result - "The expression is of type double"

// Determining the type of expression 2 * 2
if ((2 * 2) is int)
    Console.WriteLine("Type int");
else
if ((2 * 2) is uint)
    Console.WriteLine("Type uint");
else
if ((2 * 2) is long)
    Console.WriteLine("Type long");
else
if ((2 * 2) is byte)
    Console.WriteLine("Тип byte");
// Result - "Type int"

   

5. How does the is operator work when classes are inherited? Examples

The advantages of using dynamic type identification are particularly apparent in the case of class inheritance. If there is a reference to the base class, then this link can be used to determine the type of object in the inheritance hierarchy.

Example 1. Let 2 classes be given which form a hierarchy. BaseClass is base class. The DerivedClass class is derived from the BaseClass class. With the help of the is operator, the class object is determined to belong to a given type and the object is compatible with a given type.

// base class
class BaseClass
{
    public int d;
}

// derived class from the base class
class DerivedClass : BaseClass
{
    public int dd;
}

The following demonstrates the use of objects of the base and derived classes in conjunction with the is operator

// creating objects of BaseClass and DerivedClass classes
BaseClass bc = new BaseClass();
DerivedClass dc = new DerivedClass();

// the use of objects bc and dc
if (bc is BaseClass)
    Console.WriteLine("Object bc is of type BaseClass");
if (bc is DerivedClass)
    Console.WriteLine("Object bc is compatible with DerivedClass");
if (dc is BaseClass)
    Console.WriteLine("Object dc is compatible with BaseClass");
if (dc is DerivedClass)
    Console.WriteLine("Object dc is of type DerivedClass");

As a result of the above code, the following will be displayed

Object bc is of type BaseClass
Object dc is compatible with BaseClass
Object dc is of type DerivedClass

In the line

...
if (bc is DerivedClass)
    Console.WriteLine("Object bc is compatible with DerivedClass");
...

the condition value in the if statement is false, since the base class object cannot be compatible with the derived class. However, on the contrary, the derived class object is compatible with the base class, since the derived class extends the capabilities of the base class.

Example 2. There are 3 classes with the names A, B, C that form a hierarchy: class A is basic, class B inherits class A, class C inherits class B. The declaration of classes has the following form:

// base class
class A
{
    public int a;
}

// class B inherits A
class B : A
{
    public int b;
}

// class C inherits B
class C : B
{
    public int c;
}

Below is an example that determines the type of an object of class B and its compatibility with types A, C.

// the object of class B
B objB = new B();

if (objB is A)
    Console.WriteLine("objB is compatible with type A ");
if (objB is B)
    Console.WriteLine("objB is of type B");
if (objB is C)
    Console.WriteLine("obJB is compatible with type C");

As a result of executing the above code, a message will be displayed on the screen:

objB is compatible with type A
objB is of type B

   

6. Operator as. General form

The as operator is used in tasks in which type casting operations are performed. If the type conversion is unsuccessful, an exception is generated. The as operator is intended to prevent the occurrence of an exceptional situation in the case of a failed type conversion.

The general form of the as operator is:

expression as type

here expression is a separate expression that is cast to type. If the expression is typed to the type correctly, then the result of the as operation is a type reference. Otherwise, the result of the as operation is null reference.

In view of the above, the general form of the as operator, which is located on the right-hand side of the assignment operator, is:

objName = expression as type;

here objName – the name of the object that will contain the result. The result may be null or a reference to an object of class type.

   

7. An example of using the as operator

In the example, the as operator is used for the preceding check for the correctness of the type cast without raising an exception.

Let classes A, B, C be declared which form a hierarchy

// base class
class A
{
    public int a;
}

// class B inherits A
class B : A
{
    public int b;
}

// class C inherits B
class C: B
{
    public int c;
}

The following demonstrates the use of the as operator for classes A, B, C

// objects of classes A, B, C
A objA = new A();
B objB = new B();
C objC = new C();

// try to perform a cast, if possible
// the result of casting the objA object is entered into objB
objB = objA as B;
if (objB == null)
    Console.WriteLine("It is impossible to convert ObjA to the type B ");
else
    Console.WriteLine("It is possible to convert objA to type B ");

// another attempt to convert objC to type B, the result in objB
objB = objC as B;

// output of the result
if (objB == null)
    Console.WriteLine("It is impossible to convert objC to the type B ");
else
    Console.WriteLine("It is possible to convert objC to type B ");

As a result of executing the above code, the screen will be displayed

It is impossible to convert objA to type B
It is possible to convert objC to type B

   

8. How can the as operator be replaced by the is operator? Example

In this example, the as operator is replaced with the is operator. First, a check is performed on the admissibility of type casting, and only then the cast occurs. Let three classes A, B, C be given which have such declaration

// base class
class A
{
    public int a;
}

// class B inherits A
class B : A
{
    public int b;
}

// class C inherits B
class C : B
{
    public int c;
}

Below is a code snippet that uses the is operator to determine the validity of a cast. There is a check using the if statement

// objects A, B, C of classes
A objA = new A();
B objB = new B();
C objC = new C();

// attempt to cast objA, objC to type B using the is operator
if (objA is B)
    objB = (B)objA;
else
    objB = null;

if (objB == null)
    Console.WriteLine("It is impossible to convert objA to the type B");
else
    Console.WriteLine("It is possible to convert objA to the type B");

// checking objC in the same way
if (objC is B)
    objB = (B)objC;
else
    objB = null;

if (objB == null)
    Console.WriteLine("It is impossible to convert objC to the type B");
else
    Console.WriteLine("It is possible to convert objC to the type B");

As a result of executing the above code, the following result will be displayed

It is impossible to convert objA to the type B
It is possible to convert objC to the type B

   


Related topics