How to set up smartphones and PCs. Informational portal
  • home
  • Advice
  • Casting to float c #. Type conversion

Casting to float c #. Type conversion

Let's move on to examples. Class Testing, containing examples, is a set of data of different types, on which operations are performed that illustrate type conversions. Here is the class description

Testing: using System;
namespace TypesProject
{
public class Testing{
/// < summary>
/// a set of scalar fields of different types.
///
private byte b= 255;
private int x= 11 ;
private uint ux= 1111 ;
private float y= 5.5f;
private double dy= 5.55;
private string s= "Hello!";
private string si= "25";
private object obj= new Object ();
// Next are the methods of the class, given along the way
// example descriptions
}
}

The dataset of a class includes scalar data of arithmetic type related to value types, variables of string type and type object, belonging to reference types. Consider a closed (private) the method of this class is a procedure WholsWho with a formal class argument Object. The procedure prints to the console the name of the argument passed to it, its type and value.

Here is its text:

/// < summary>
/// The method prints information about the type to the console and
/// the value of the actual argument. Formal
/// the argument is of typeobject. The actual argument
/// can be of any type, since always
/// implicit conversion to type is allowedobject.
///
/// Namesecondargument
/// Let's admitargumentanytype
private void WhoIsWho (string name, object any){
Console.WriteLine ("type{0} is (1), value is{2}",
name, any.GetType (), any.ToString ());
}

Here is open (public) class method Testing, in which the method is called repeatedly WholsWho with arguments of different types:

/// < summary>
/// get information about the type and value
/// of the passed argument - variable or expression
/// summary>
public void WhoTest (){
WholsWho ("x", x);
WholsWho ("ux", ux);
WhoIsWho ("y", y);
WhoIsWho ("dy", dy);
WhoIsWho ("s", s);
WhoIsWho ("11+ 5.55 + 5.5f ", 11+ 5.55 + 5.5f);
obj= 11 + 5.55 + 5.5f;
WhoIsWho(" obj", obj);
}

Note that the entity any- formal class argument Object, which, on each call, dynamically changes the type by associating with the object given by the actual argument. Therefore, the type of the argument reported to the console is the type of the actual argument. Note also that the class inherited from the class Object method Gettype returns the FCL type, that is, the type that reflects the type of the language and with which the work is actually carried out when the module is executed. In most calls, the actual argument is a variable - the corresponding property of the class Testing, but in one case, an ordinary arithmetic expression is passed, automatically converted to an object. A similar situation takes place when performing an assignment in the procedure under consideration.

In fig. 11 shows the output to the console when the method was called WhoTest in the above procedure Main class Classi.

Figure 11. Printing the WhoTest test results

Where, how, and when are type conversions performed?

The need for type conversion arises in expressions, assignments, replacement of formal method arguments with actual ones.

If, when evaluating an expression, the operands of an operation have different types, then it becomes necessary to cast them to the same type. Such a need arises also when the operands are of the same type, but it is inconsistent with the type of the operation. For example, when performing addition, operands of type byte must be cast to type int, since addition is not defined over bytes. When doing an assignment x= e source type e and target type x must be consistent. Likewise, when calling a method, the source and target types of actual and formal arguments must also be consistent.

Reference type conversions

Since operations on reference types are not defined (the exception is strings, but operations on them, including assignment, are performed as on value types), the need for them arises only during assignments and method calls.

Type conversions in expressions

In C #, such conversions are divided into implicit and explicit. Implicit conversions are those conversions, the result of which is always successful and does not lead to a loss of data accuracy. Implicit conversions are done automatically. For arithmetic data, this means that in implicit conversions, the range of the target type contains the range of the original type. For example, a conversion from type byte in type int refers to implicit because the range is like byte is a subset of the range int. This conversion is always successful and cannot result in a loss of precision.

Explicit conversions are legal conversions that are not guaranteed to succeed or may result in a loss of precision. Such potentially dangerous conversions must be explicitly specified by the programmer. Conversion from type int in type byte refers to explicit because it is unsafe and can lead to loss of significant digits. Note that not all types have explicit conversions. In this case, other type conversion mechanisms are required, which will be discussed later.

Conversions within an arithmetic type

The arithmetic type, as shown in the datatype table, splits into 11 subtypes. In fig. 12 shows a diagram of conversions within an arithmetic type.

Figure 12. Hierarchy of conversions within an arithmetic type

The diagram shown in the figure allows you to answer a number of important questions related to the existence of conversions between types. If the diagram shows a path (arrows) from type A to type B, then this means the existence of an implicit conversion from type A to type B. All other conversions between subtypes of arithmetic type exist, but are explicit. Note that there are no cycles in the diagram, all arrows are one-way, so the inverse to implicit conversion must always be specified explicitly.

The path shown in the diagram can be quite long, but this does not mean that the entire sequence of transformations on this path is being performed. The presence of a path only indicates the existence of an implicit conversion, and the conversion itself is performed only once, from source type A to destination type B.

Sometimes a situation arises in which for one type of source several types of destinations can exist simultaneously and it is necessary to select a target - the type of destination. Such selection problems arise, for example, when working with overloaded methods in classes.

The rule for choosing an implementation when calling a method is as follows: the implementation is selected for which the transformation path specified in the diagram is shorter. If there is an exact match of the parameters by type (path of length 0), then, of course, this implementation will be chosen.

Let's look at another test case. To class Testing a group of overloaded methods is included OLoad with one and two arguments. These methods are:

/// < summary>
/// Group of overloaded methodsOLoad
/// with one or two arithmetic type arguments.
/// If the actual argument is one, then one of the
/// methods that most closely match the type of the argument.
/// When calling a method with two arguments, it is possible
/// Conflict in choosing an appropriate method, resulting in
/// to a compile-time error.
///
private void OLoad (float par){
Console.WriteLine ("float value{0}", par);
}
/// < summary>
/// Overloaded methodOLoadwith one type parameterlong
///
///
private void OLoad (long par){
Console.WriteLine ("long value (0)", par);
}
/// < summary>
/// Overloaded methodOnLoadwith one type parameterulong
///
///
private void OLoad (ulong par){
Console.WriteLine ("ulong value (0)", par);
}
/// < summary>
/// Overloaded methodOLoadwith one type parameterdouble
///
///
private void OnLoad (double par){
Console.WriteLine ("double value (0)", par);
}
/// < summary>
/// Overloaded methodOLoadwith two parameters likelongandlong
///
///
///
private void OLoad (long par1, long par2){
Console.WriteLine ("long par1{0}, long par2{1}", par1, par2);
}
/// < summary>
/// Overloaded methodOLoadwith two parameters like
/// doubleanddouble
///
///
///
private void OLoad (double par1, double par2){
Console.WriteLine ("double par1{0}, double par2{1}", par1, par2);
}
/// < summary>
/// Overloaded methodOLoadwith two parameters like
/// intandfloat
///
///
///
private void OLoad (int par1, float par2){
Console.WriteLine ("int par1{0}, float par2{1}", par1, par2);
}

All these methods are simple enough. They provide information about the type and value of the arguments passed.

Here is a test procedure that calls the method OLoad with different number and types of arguments:

/// < summary>
/// Calling an overloaded methodOLoad. Depending on the
/// type and number of arguments one of the group methods is called.
///
public void OLoadTest (){
OLoad (x);
OLoad (ux);
OLoad (y);
OLoad (dy);
// OLoad (x, ux);
// conflict: (int, float)and(long, long)
OLoad (x, (float) ux);
OLoad (y, dy);
OLoad(x, dy);
}

Note that one of the calls is commented out as it leads to a conflict during the translation phase. To eliminate the conflict when calling the method, we had to specify an explicit conversion of the argument, which is shown in the line following the comment line. Test result OLoadTest is shown in Fig. thirteen.

Figure 13. Printing OLoadTest results

Explicit conversions

As mentioned earlier, explicit conversions can be dangerous because of the loss of precision. Therefore, they are executed at the direction of the programmer - he bears all responsibility for the results.

String conversions

An important class of conversions are conversions to string and vice versa. Conversions to a string type are always defined, since all types are descendants of the base class Object, and, therefore, have the method ToString(). A suitable implementation of this method has been defined for built-in types. In particular, for all subtypes of arithmetic type, the method ToString() returns in suitable form a string specifying the corresponding arithmetic value. Note, the method ToString can be called explicitly, but if an explicit call is not specified, then it will be called implicitly, whenever the context requires a conversion to a string type. Here's a relevant example:

/// < summary>
/// Demonstration of converting data of various types into a string.
///
public void ToStringTest ()
{
s= " VladimirPetrov ";
s1= " Age: ";
ux= 27;
s= s+ s1+ ux.ToString ();
s1= " Salary: ";
dy= 2700.50;
s= s+ s1+ dy;
WhoIsWho(" s", s);
}

The result of this procedure is shown in Fig. 14.

Figure 14. Printing the results of ToStringTest

Conversions from a string type to other types, such as arithmetic, must be done explicitly. But there are no explicit conversions between arithmetic and strings. Other mechanisms are needed, and they are available in C #. For this purpose, you can use the corresponding class methods Convert FCL library embedded in namespace System. Let's give an example:

/// < summary>
/// Demonstration of converting a string into data of various types.
///
public void FromStringTest (){
s= " Enterage ";
Console.WriteLine (s);
s1= Console.ReadLine ();
ux= Convert.ToUInt32 (s1);
WhoIsWho("Age: ",ux);
s= "Enter salary";
Console.WriteLine (s);
s1= Console.ReadLine ();
dy= Convert.ToDouble (s1);
WhoIsWho ("Salary: ", dy);
}

This example demonstrates input from the console of different types of data. Data read from console by method ReadLine or Read, always represent a string, which must then be converted to the desired type. For this, the corresponding class methods are called. Convert. Naturally, for the conversion to succeed, the string must contain a value in a format that allows such conversion. Note, for example, that when writing the value of a number, a comma, not a period, must be used to highlight the fractional part; otherwise, a runtime error will occur.

In fig. 15 shows the results of output and input from the console when this procedure is running.

Figure 15. Printing the results of the FromStringTest

Implicit data type conversion is performed by the C ++ compiler, while the explicit data type conversion is performed by the programmer himself. About data type conversion I will say the following: "The result of any calculation will be converted to the most accurate data type of those data types that are involved in the calculation." For an illustrative example, I will present a table with data type conversions. Let's look at the division operation in the table. As an integer data type, we take int, well, we will have a real data type float.

Table 1 - Explicit and Implicit Data Type Conversion in C ++
x y Division Result Example
dividend divider private x = 15 y = 2
int int int 15/2=7
int float float 15/2=7.5
float int float 15/2=7.5

The table shows that changing the variables in different places, the result remains the same (in our case, this is the dividend and divisor). It's all about implicit data type conversion. As for the explicit conversion, it is necessary in order to perform some manipulations, thereby changing the result of the calculation. The easiest way to explicitly convert data types, for example: let's say we need to divide such numbers 15 and 2, we divide! 15/2 = 7. The result is the same as in the table. But if you make minor transformations, for example: 15.0 / 2 = 7.5 with this division, the number 15 is real, then the result will be real. The number 15 itself has not changed from the point of view of mathematics, because 15 = 15.0. The same technique could be applied to two, the result would be the same, but it could be applied to two numbers at once, but why, if one of the two is enough.

Another way to explicitly convert data types:

Float (15) / 2 // the result is 7.5, the number 15 is converted to the real data type float. double (15) / 2 // result is 7.5 - the same !!!

C ++ also provides a unary cast operation:

Static_cast(/ * variable or number * /)

example: static_cast (15) / 2 the result is 7.5
Example with a variable:

Int ret = 15; static_cast (ret) / 2 // result is 7.5

In the case of a variable, you need to understand that in line 2, the ret variable is not converted to the float data type, but only a temporary copy of the ret variable with the float data type is created. Let's consider in practice all the methods of explicit and implicit conversion of data types.

// pryeobrazovanie.cpp: Defines the entry point for the console application. #include "stdafx.h" #include #include using namespace std; int _tmain (int argc, _TCHAR * argv) (int int_value15 = 15, int_value2 = 2; // declare two variables of type int float float_value15 = 15, float_value2 = 2; // declare two variables of type float cout<< fixed << setprecision(2) // определяем, при выводе чисел с плавающей точкой, два знака после запятой << "15 / 2 = " << int_value15 / int_value2 << endl //неявное преобразование типов данных << "15 / 2 = " << int_value15 / float_value2 << endl //неявное преобразование типов данных << "15 / 2 = " << float_value15 / int_value2 << endl //неявное преобразование типов данных << "15 / 2 = " << float_value15 / float_value2 << endl; //неявное преобразование типов данных cout << "15.0 / 2 = " << 15.0 / 2 << endl // явное преобразование типа данных, число 15.0 - число с плавающей точкой << "15 / 2.0 = " << 15 / 2.0 << endl; // явное преобразование типа данных, число 2.0 - число с плавающей точкой cout << "float(int_value15) / int_value2 = " << float(int_value15) / int_value2 << endl // явное преобразование типа данных << "15 / double(2) = " << 15 / double(2) << endl; // используя приводимый тип как функцию cout << "static_cast(15) / 2 = " << static_cast(15) / 2 << endl // унарная операция приведения типа << "static_cast(15) = " << static_cast(15) << endl // можно печатать различные символы из таблицы ASCII, << "static_cast(20) = " << static_cast(20) << endl; // в скобочках прописываем код символа, который находим в таблице ASCII system("pause"); return 0; }

V line 5 connected , this library is needed to use various manipulators, in our case - fixed setprecision (). V line 10specially created two variables like int , similarly created two variables of type float in line 11, these variables will be needed to convert their values ​​to other data types. Vline 12after operator cout and shift operations to the output stream << there are two manipulators fixed and setprecision (). Fixed manipulator - this is not a parameterized manipulator, since it does not accept any parameters, it is written without parentheses. This manipulator is used in conjunction with a parameterized manipulator setprecision () and performs a fixed display of the decimal places. A manipulator setprecision () displays the number of decimal places, and that which is indicated in parentheses. Vlines 13, 14, 15, 16examples of implicit data type conversion are shown, these examples are taken fromtable 1... V lines 17, 18shows one of the ways to explicitly transform data. The essence of this method is that you need to add a comma and zero to an integer. Vlines 19, 20explicit conversion is performed by using castable types as functions, inside the parentheses of which, you need to specify the value or variable to be converted. In lines 21, 22, 23, an explicit data type conversion is performed using a unary data conversion operation. The parentheses indicate the variable or value to be converted, and the characters are framed < > the data type to convert to. An example of how the program works is shown below (see Figure 1).

Figure 1 - Explicit and implicit conversion of C ++ data types

V lines 22, 23 a unary data conversion operation is performed, and the numbers 15 and 20 are converted to char. This datatype is not yet known to you, but remember that char is the datatype for storage. So, from Figure 1 you can see that there are symbols at the end. These characters were obtained by converting numbers to char. The numbers were codes from. Thus, if you need to display any character from the ASCII table, this can be done as shown in lines 22, 23, while substituting only the required code.

Type conversions

In programming, it is not uncommon for the values ​​of variables of one type to be assigned to variables of another type. For example, in the following code snippet, an int is assigned to a float:

Int i; float f; i = 10; f = i; // assign an integer value to a float variable

If compatible data types are mixed in one assignment operation, then the value on the right side of the assignment operator is automatically converted to the type indicated on the left side of it. Therefore, in the above code snippet, the value of i is first converted to float and then assigned to f. However, due to strict type control, not all data types in C # are completely compatible, and therefore, not all type conversions are allowed implicitly. For example, the types bool and int are incompatible. True, the conversion of incompatible types can still be done by bringing... Typecasting essentially means converting them explicitly.

Automatic type conversion

When data of one type is assigned to a variable of another type, implicit conversion types occurs automatically under the following conditions:

  • both types are compatible
  • the range of representation of numbers of the target type is wider than that of the original type

If both of these conditions are satisfied, then widening transform... For example, int is large enough to hold all valid values ​​of byte, and besides, both int and byte are compatible integer types, and therefore implicit conversion is quite possible for them.

Numeric types, both integer and floating point, are quite compatible with each other for performing widening conversions. Let's consider an example:

Using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 (class Program (static void Main (string args) (short num1, num2; num1 = 10; num2 = 15; Console.WriteLine ("(0) + (1) = (2)", num1, num2, Sum (num1, num2)); Console.ReadLine ();) static int Sum (int x, int y) (return x + y;)))

Note that the Sum () method expects two int parameters to arrive. However, in the Main () method, it is actually passed two variables of type short. While this may seem like a type mismatch, the program will compile and run without error, and return 25 as expected.

The reason why the compiler will consider this code to be syntactically correct is because data loss is impossible here. Since the maximum value (32767) that a short can hold is well within the range of an int (whose maximum value is 2147483647), the compiler will implicitly expand each short to an int. Formally, the term "extension" is used to denote an implicit upward cast that does not result in data loss.

Casting incompatible types

While implicit conversions are useful, they fail to meet all programming needs because they only allow widening conversions of compatible types. And in all other cases, you have to resort to type conversion. Bringing is a command to the compiler to convert the result of evaluating an expression to the specified type. This requires an explicit type conversion. The following is the general form of typecasting:

(target_type) expression

Here target_type denotes the type to which you want to convert the specified expression.

If the casting results in narrowing transformation, then some of the information may be lost. For example, as a result of casting from type long to type int, some information will be lost if the value of type long is larger than the range of representation of numbers for type int, since the most significant bits of this numeric value are discarded. When a floating point value is cast to an integer value, the fractional part of this numeric value is lost as a result of truncation. So, if you assign the value 1.23 to an integer variable, then as a result only the whole part of the original number (1) will remain in it, and its fractional part (0.23) will be lost. Let's take an example:

Using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 (class Program (static void Main (string args) (int i1 = 455, i2 = 84500; decimal dec = 7.98845m; // Cast two numbers of type int // to type short Console.WriteLine ((short) i1) ; Console.WriteLine ((short) i2); // Cast a decimal // type to int Console.WriteLine ((int) dec); Console.ReadLine ();)))

The result of this program will be:

Please note that the variable i1 was correctly converted to type short, since its value is in the range of this data type. Converting dec to int returned the integer portion of that number. Converting the variable i2 returned overflow value 18964 (i.e. 84500 - 2 * 32768).

Interception of narrowing data transformations

In the previous example, casting the variable i2 to short is not acceptable, since arises data loss... C # suggests keywords such as checked and unchecked to ensure that data loss does not go unnoticed.

By default, when no appropriate corrective action is taken, overflow and underflow conditions occur without an error. There are two ways to handle overflow and underflow conditions in your application. This can be done manually by relying on your programming knowledge and skills.

The disadvantage of this approach is that even in the case of applying maximum efforts, a person still remains a person, and some mistakes can slip away from his eyes.

Fortunately, C # provides the checked keyword. When a statement (or statement block) is enclosed in a checked context, the C # compiler generates additional CIL statements to check for overflow conditions that can result from addition, multiplication, subtraction, or division of two numeric data types.

If an overflow condition occurs at runtime, an exception will be thrown System.OverflowException... Let's look at an example in which we will send the value of the exception to the console:

Using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 (class Program (static void Main (string args) (byte var1 = 250; byte var2 = 150; try (byte sum = checked ((byte) (var1 + var2)); Console.WriteLine ("Sum: (0 ) ", sum);) catch (OverflowException ex) (Console.WriteLine (ex.Message); Console.ReadLine ();))))

The result of this program:

Set up a project-wide check for overflow conditions

If you are building an application in which overflow should never go unnoticed, you might find that wrapping around with the checked keyword is an annoyingly large number of lines of code. In such a case, as an alternative, the C # compiler supports flag / checked... When this flag is activated, all arithmetic operations in the code will be automatically checked for possible overflows, without using the checked keyword for each of them. Overflow detection likewise results in the corresponding exception being thrown at runtime.

To activate this flag in Visual Studio 2010, open the project properties page, go to the Build tab, click on the Advanced button and check the box in the dialog box that opens Check for arithmetic overflow / underflow:

It is important to note that C # provides the keyword unchecked, which allows you to disable the throwing of an overflow exception in individual cases.

So, to summarize the use of the checked and unchecked keywords in C #, note that by default, arithmetic overflow is ignored in the .NET runtime. If you need to process individual operators, then the checked keyword should be used, and if you need to catch all overflow-related errors in the application, then you need to activate the / checked flag. As for the unchecked keyword, it can be used when there is a block of code in which the overflow is legal (and therefore should not result in an exception being thrown at runtime).

Last update: 30.07.2018

In the previous chapter, we talked about converting objects of simple types. Now let's touch on the topic of converting class objects. Let's say we have the following class hierarchy:

Class Person (public string Name (get; set;) public Person (string name) (Name = name;) public void Display () (Console.WriteLine ($ "Person (Name)");)) class Employee: Person ( public string Company (get; set;) public Employee (string name, string company): base (name) (Company = company;)) class Client: Person (public string Bank (get; set;) public Client (string name, string bank): base (name) (Bank = bank;))

In this class hierarchy, we can trace the following chain of inheritance: Object (all classes implicitly inherit from the Object type) -> Person -> Employee | Client.

Moreover, in this class hierarchy, base types are at the top, and derived types are at the bottom.

Upstream transformation. Upcasting

Objects of a derived type (which is at the bottom of the hierarchy) also represent the base type. For example, the Employee object is also an object of the Person class. Which, in principle, is natural, since each employee (Employee) is a person (Person). And we can write, for example, like this:

Static void Main (string args) (Employee employee = new Employee ("Tom", "Microsoft"); Person person = employee; // convert from Employee to Person Console.WriteLine (person.Name); Console.ReadKey (); )

In this case, the variable person, which represents the type Person, is assigned a reference to the Employee object. However, to store a reference to an object of one class into a variable of another class, you need to perform a type conversion — in this case, from the Employee type to the Person type. And since Employee inherits from the Person class, an implicit up-conversion is automatically performed - converting to the types that are at the top of the class hierarchy, that is, to the base class.

As a result, the variables employee and person will point to the same object in memory, but only the part that represents the functionality of the Person type will be available to the person variable.

Other upstream transformations are done in a similar way:

Person person2 = new Client ("Bob", "ContosoBank"); // convert from Client to Person

Here, the variable person2, which represents the type Person, holds a reference to the Client object, so an implicit bottom-up conversion is also performed from the derived Client class to the base Person type.

The upward implicit conversion will also occur in the following case:

Object person1 = new Employee ("Tom", "Microsoft"); // Employee to object object person2 = new Client ("Bob", "ContosoBank"); // from Client to object object person3 = new Person ("Sam"); // Person to object

Since the object type is basic for all other types, the conversion to it will be done automatically.

Downward transformations. Downcasting

But in addition to upstream conversions from derived to base type, there are downcasting or downcasting from base type to derived. For example, in the following code, the variable person stores a reference to the Employee object:

Employee employee = new Employee ("Tom", "Microsoft"); Person person = employee; // convert from Employee to Person

And the question may arise whether it is possible to access the functionality of the Employee type through a variable of the Person type. But such transformations do not go through automatically, because not every person (Person object) is an employee of the enterprise (Employee object). And for a downward conversion, you need to apply explicit conversions, specifying the type in parentheses to which you want to convert:

Employee employee = new Employee ("Tom", "Microsoft"); Person person = employee; // convert from Employee to Person // Employee employee2 = person; // this is not possible, you need an explicit transformation Employee employee2 = (Employee) person; // convert from Person to Employee

Let's look at some examples of transformations:

// The Employee object is also of type object object obj = new Employee ("Bill", "Microsoft"); // to access the capabilities of the Employee type, cast the object to the Employee type Employee emp = (Employee) obj; // the Client object also represents the Person type Person person = new Client ("Sam", "ContosoBank"); // convert from Person to Client Client client = (Client) person;

In the first case, the variable obj is assigned a reference to the Employee object, so we can convert the obj object to any type that is located in the class hierarchy between the type object and Employee.

If we need to refer to some individual properties or methods of an object, then we do not need to assign the transformed object to a variable:

// The Employee object is also of type object object obj = new Employee ("Bill", "Microsoft"); // cast to Person to call Display ((Person) obj) .Display (); // or so // ((Employee) obj) .Display (); // cast to Employee to get Company property string comp = ((Employee) obj) .Company;

At the same time, care must be taken when making such conversions. For example, what happens in the following case:

// The Employee object is also of type object object obj = new Employee ("Bill", "Microsoft"); // cast to Client to get Bank property string bank = ((Client) obj) .Bank;

In this case, we will get an error because the obj variable holds a reference to the Employee object. This object is also an object of types object and Person, so we can convert it to these types. But we cannot convert to Client type.

Another example:

Employee emp = new Person ("Tom"); //! Error Person person = new Person ("Bob"); Employee emp2 = (Employee) person; //! Error

In this case, we are trying to convert an object of type Person to type Employee, and the Person object is not an Employee object.

There are a number of ways to avoid these conversion errors.

Conversion methods

First, the as keyword can be used. Using it, the program tries to convert the expression to a specific type without throwing an exception. In case of unsuccessful conversion, the expression will contain the null value:

Person person = new Person ("Tom"); Employee emp = person as Employee; if (emp == null) (Console.WriteLine ("Conversion failed");) else (Console.WriteLine (emp.Company);)

The second way is to catch the InvalidCastException that is thrown as a result of the conversion:

Person person = new Person ("Tom"); try (Employee emp = (Employee) person; Console.WriteLine (emp.Company);) catch (InvalidCastException ex) (Console.WriteLine (ex.Message);)

The third way is to test the validity of the conversion using the is keyword:

Person person = new Person ("Tom"); if (person is Employee) (Employee emp = (Employee) person; Console.WriteLine (emp.Company);) else (Console.WriteLine ("No conversion allowed");)

The person is Employee expression tests whether the person variable is an object of type Employee. But since in this case it is clearly not, then such a check will return false, and the conversion will not work.

Top related articles