Skip to main content

📓 Type Casting

Type casting is the process of transferring a piece of data between types. We'll look at an example in the dotnet-script REPL using standard data types.

Type Casting

Let's try to multiply a decimal-holding number, which is called a double, and store it in an integer.

> double myNumber = 12.5;
> int multipliedNumber = myNumber * 2;

We'll quickly get an error:

(1,24): error CS0266: Cannot implicitly convert type 'double' to 'int'. An explicit conversion exists (are you missing a cast?)

When we multiply 12.5 * 2 we get 25, which should be a valid integer. Well, even though the result of the operation is a whole number, and we're storing that whole number in a variable declared as an int, C# throws an error because double is not an int. Moreover, C# does not make any implicit conversions between double and int. This is our strongly-typed paradigm at work.

Explicit Casting

The error hints at a solution: An explicit conversion exists (are you missing a cast?) What is an explicit conversion? Let's look at how we can use one to compile this code. We've already entered in double myNumber = 12.5; to the REPL, so now we'll just fix the arithmetic by adding a data type conversion:

> int multipliedNumber = (int)myNumber * 2;
> multipliedNumber

The syntax (int)myNumber is an example of a cast. Casting, just like in the movies, is the act of turning one thing into another. Just as Audrey Hepburn was cast as Holly Golightly in the movie "Breakfast at Tiffany's", we can cast double as an int.

This type of cast is called an explicit cast. We're openly telling the compiler to convert myNumber into an integer before proceeding. Since myNumber and 2 are both valid integers, their evaluation can be stored in the multipliedNumber variable.

Casting Does Not Always Go As Expected

But there's still something wrong! We got 24 instead of 25, the actual result of 12.5 * 2. So why doesn't C# return 25?

Casting can be an imperfect process. When data types are different, casting can sometimes result in a loss in accuracy. In this case, the expression (int)myNumber converts 12.5 into an integer before performing the multiplication operation. To convert a double into an int, our cast drops the decimal and turns myNumber into 12. As we know, 12 * 2 equals 24.

This is called lossy conversion, as there is a loss of data or accuracy that occurs during the conversion.

We can mitigate this loss by waiting until the operation completes before performing the conversion:

> double myNumber2 = 12.5;
> int multipliedNumber2 = (int)(myNumber2 * 2); //CHANGE IS HERE
> multipliedNumber2

We perform our mathematical operation before making the explicit conversion, which leads to the correct result, 25.

Implicit casting

There is another cast going on here that we might not spot right away. In our expression myNumber * 2, the 2 is declared without a type. It's just a numeric value.

So what type is 2 exactly if we haven't declared it?

Let's change our example slightly:

> int myNumber3 = 12;
> double multipliedNumber3 = myNumber3 * 2;
> multipliedNumber3

When we run this code, we get the correct value 24. How does a multiplied int become a double when a multiplied double cannot become an int?

When we convert 12.5 to an int, we lose information. It would make sense to think of a double as a data type that contains more information than an int. This makes a double a larger data type than an int. When we convert from an int to a double, we don't lose any information because we're moving from a smaller data type to a larger one. This is called implicit casting. No special syntax is required and C# will do this automatically.

So what is 2 in the code above then?

It starts as an int. However, because it's a smaller data type than a double, C# implicitly casts it to a double so it can be evaluated.

Other Implicit Casting

There are other types of implicit conversions that C# performs. For example, if we have an integer and use string interpolation to have the integer evaluated within a string, C# will automatically convert the integer into a string. Here's two examples:

> $"Hello number {1}"
"Hello number 1"
> int num = 2;
> $"Hello number {num}"
"Hello number 2"

If you want to learn more, or are ever unsure of whether C# is converting data types implicitly, review all of the cases in which C# performs implicit conversions on the Microsoft (MS) Docs.

Guidelines and Resources

Here are some guidelines for explicit and implicit casting. In general, we shouldn't be using type casting frequently; regular use of type casting is a sign that the code is inefficient.

C# will perform implicit casting when:

  • Data types are compatible, such as when we are working with two ints;
  • When data of a smaller type is assigned to a bigger data type, such as when an int is cast as a double.

We should use explicit casting when:

  • We are working with incompatible data types where automatic conversion cannot be done. We explicitly state the data type to which the value should be converted. However, be careful: explicit casting can potentially result in loss of accuracy.

Would you like to see more examples? The Microsoft (MS) Docs has a great article on casting and type conversion.