You will often need to convert between different types.
Add a new console application project named Ch03_CastingConverting
.
It is safe to implicitly cast an int
variable into a double
variable.
In the Main
method, enter the following statements:
int a = 10; double b = a; // an int can be stored in a double WriteLine(b);
You cannot implicitly cast a double
variable into an int
variable because it is potentially unsafe and would lose data.
In the Main
method, enter the following statements:
double c = 9.8; int d = c; // compiler gives an error for this line WriteLine(d);
In Visual Studio 2017, press Ctrl + W, E to view the Error List, as shown in the following screenshot:
In Visual Studio Code, either view the Problems window, or when you enter the command dotnet run
, you will see the following output:
Compiling Ch03_CastingConverting for .NETCoreApp,Version=v1.1 /usr/local/share/dotnet/dotnet compile-csc @/Users/markjprice/Code/Chapter03/Ch03_CastingConverting/obj/ Debug/netcoreapp1.1/dotnet-compile.rsp returned Exit Code 1 /Users/markjprice/Code/Chapter03/Ch03_CastingConverting/Program.cs(14 ,21): error CS0266: Cannot implicitly convert type 'double' to 'int'. An explicit conversion exists (are you missing a cast?) Compilation failed. 0 Warning(s) 1 Error(s) Time elapsed 00:00:01.0461813
You must explicitly cast a double
into an int
variable using a pair of round brackets around the type you want to case the double
into. The pair of round brackets is the cast operator. Even then, you must beware that the part after the decimal point will be trimmed off without warning.
Modify the assignment statement for the variable d
, as shown in the following code:
double c = 9.8;
int d = (int)c;
WriteLine(d); // d is 9 losing the .8 part
Run the console application and view the output:
10 9
We must perform a similar operation when moving values between larger integers and smaller integers. Again, beware that you might lose information because any value too big will get set to -1
!
Enter the following code:
long e = 10; int f = (int)e; WriteLine($"e is {e} and f is {f}"); e = long.MaxValue; f = (int)e; WriteLine($"e is {e} and f is {f}");
Run the console application and view the output:
e is 10 and f is 10 e is 9223372036854775807 and f is -1
An alternative to using the casting operator is to use the System.Convert
type.
At the top of the Program.cs
file, type the following code:
using static System.Convert;
Add the following statements to the bottom of the Main
method:
double g = 9.8; int h = ToInt32(g); WriteLine($"g is {g} and h is {h}");
Run the console application and view the output:
g is 9.8 and h is 10
The System.Convert
type can convert to and from all the C# number types as well as Booleans, strings, and date and time values.
You have now seen that the cast operator trims the decimal part of a real number and that the convert methods round up or down. However, what is the rule for rounding?
In British primary schools, children are taught to round up if the decimal part is .5
or higher and round down if the decimal part is less.
Enter the following code:
double i = 9.49; double j = 9.5; double k = 10.49; double l = 10.5; WriteLine($"i is {i}, ToInt(i) is {ToInt32(i)}"); WriteLine($"j is {j}, ToInt(j) is {ToInt32(j)}"); WriteLine($"k is {k}, ToInt(k) is {ToInt32(k)}"); WriteLine($"l is {l}, ToInt(l) is {ToInt32(l)}");
Run the console application and view the output:
i is 9.49, ToInt(i) is 9 j is 9.5, ToInt(j) is 10 k is 10.49, ToInt(k) is 10 l is 10.5, ToInt(l) is 10
Note that the rule for rounding in C# is subtly different. It will round up if the decimal part is .5
or higher and the non-decimal part is odd, but it will round down if the non-decimal part is even. It always rounds down if the decimal part is less than .5
.
This rule is known as Banker's Rounding, and it is preferred because it reduces bias. Sadly, other languages such as JavaScript use the primary school rule.
The most common conversion is from any type into a string
variable, so all types have a method named ToString
that they inherit from the System.Object
class.
The ToString
method converts the current value of any variable into a textual representation. Some types can't be sensibly represented as text so they return their namespace and type name.
Add the following statements to the bottom of the Main
method:
int number = 12; WriteLine(number.ToString()); bool boolean = true; WriteLine(boolean.ToString()); DateTime now = DateTime.Now; WriteLine(now.ToString()); object me = new object(); WriteLine(me.ToString());
Run the console application and view the output:
12 True 27/01/2017 13:48:54 System.Object
The second most common conversion is from strings to numbers or date and time values. The opposite of ToString
is Parse
. Only a few types have a Parse
method.
Add the following statements to the Main
method:
int age = int.Parse("27"); DateTime birthday = DateTime.Parse("4 July 1980"); WriteLine($"I was born {age} years ago."); WriteLine($"My birthday is {birthday}."); WriteLine($"My birthday is {birthday:D}.");
Run the console application and view the output:
I was born 27 years ago. My birthday is 04/07/1980 00:00:00. My birthday is 04 July 1980.
One problem with the Parse
method is that it gives errors if the string cannot be converted.
Add the following statements to the bottom of the Main
method:
int count = int.Parse("abc");
Run the console application and view the output:
Unhandled Exception: System.FormatException: Input string was not in
a correct format.
To avoid errors, you can use the TryParse
method instead. TryParse
attempts to convert the input string and returns true
if it can convert it and false
if it cannot. The out
keyword is required to allow the TryParse
method to set the count variable when the conversion works.
Replace the int count
declaration with the following statements:
Write("How many eggs are there? "); int count; string input = Console.ReadLine(); if (int.TryParse(input, out count)) { WriteLine($"There are {count} eggs."); } else { WriteLine("I could not parse the input."); }
Run the application twice. The first time, enter 12
. You will see the following output:
How many eggs are there? 12 There are 12 eggs.
The second time, enter twelve
. You will see the following output:
How many eggs are there? twelve I could not parse the count.
52.14.76.200