C# 6 and .NET Core 1.0:Modern Cross:Platform Development
上QQ阅读APP看书,第一时间看更新

Casting and converting between types

You will often need to convert between different types.

Add a new Console Application project named Ch03_CastingConverting.

Casting from numbers to numbers

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;
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);

Press Ctrl + W, E to view the Error List, as shown in the following screenshot:

You must explicitly cast a double into an int variable using a pair of round brackets around the type you want to cast 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

We must do 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}");

Press Ctrl + F5 and view the output in the console:

e is 10 and f is 10
e is 9223372036854775807 and f is -1

Using the Convert type

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;

We can now use a lot of ToSomeType methods.

double g = 9.8;
int h = ToInt32(g);
WriteLine($"g is {g} and h is {h}");

Note that one difference between casting and converting is that converting rounds the double value up to 10 instead of trimming the part after the decimal point.

Press Ctrl + F5 and view the output in the console:

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 dates and times.

Rounding numbers

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. But 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 beneath the code that you have already written to see the effect of converting four double variables to int variables:

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)}");

Press Ctrl + F5 and view the output in the console:

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.

Tip

Best Practice

For every programming language that you use, check its rounding rules. They may not work the way you expect!

Converting from any type to a string

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 (which can be simplified using the object keyword).

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. Enter the following statements beneath the code that you have already written to declare four variables of types int, bool, DateTime, and object, and see what their implementations of ToString return:

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());

Press Ctrl + F5 and view the output in the console:

12
True
04/03/2016 13:48:54
System.Object

Parsing from strings to numbers or dates and times

The second most common conversion is from strings to numbers or dates and times. The opposite of ToString is Parse. Only a few types have a Parse method.

Add a new Console Application project named Ch03_Parsing.

Add the following statements to the bottom of 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}.");

Press Ctrl + F5 and view the output in the console:

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");

Press Ctrl + F5 and view the output in the console:

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.
Tip

You can also use the Convert type, but like the Parse method, it gives an error if it cannot convert.