C# supports implicit type conversions. This means that if we try to assign the value of some variable y to another variable x as shown here:
x = y;
and the two variables were originally declared to be of different types, then C# will attempt to perform the assignment, automatically converting the type of the value of y to the type of x, but only if precision won't be lost in doing so. (C# differs from C and C++ in this regard, as the latter two perform automatic type conversions even if precision is lost.) This is best understood by looking at an example:
int x; double y; y = 2.7; x = y; // Trying to assign a double value to an int variable; this line will // compile in C and C++, but not in C#.
In the preceding code snippet, we're attempting to copy the double value of y, 2.7, into x, which is declared to be an int. If this assignment were to take place, the fractional part of y would be truncated, and x would wind up with an integer value of 2. This represents a loss in precision, also known as a narrowing conversion. A C or C++ compiler will permit this assignment, thereby silently truncating the value; rather than assuming that this is what we intended to do, however, the C# compiler will generate an error on the last line.
Error: CS0029: Cannot implicitly convert type 'double' to type 'int'
In order to signal to the C# compiler that we're willing to accept the loss of precision, we must perform an explicit cast, which involves preceding the expression whose value is to be converted with the desired target type enclosed in parentheses. In other words, we'd have to rewrite the last line of the preceding example as follows in order for the C# compiler to accept it:
int x; double y; y = 2.7; x = (int) y; // This will compile now. The C# compiler 'relaxes', // because we have explicitly told it that we WANT the // narrowing conversion to occur.
Of course, if we were to reverse the direction of the assignment:
int x; double y; x = 2; y = x; // Assign an int value to a double variable; y will assume the // value 2.0.
the C# compiler would have no problem with the last statement, because in this particular case, we're assigning a value of less precision—2—to a variable capable of more precision; y will wind up with the value of 2.0. This is known as a widening conversion; such conversions are performed automatically in C#, and need not be explicitly cast.
Note that there is an idiosyncrasy with regard to assigning constant values to floats in C#; the statement
float y = 3.5; // won't compile!
will generate a compiler error, because a numeric constant value with a fractional component like 3.5 is automatically treated by C# as a more precise double value, and so the compiler will once again refuse to make a transfer that causes precision to be lost. To make such an assignment, we must explicitly cast the floating point constant into a float:
float y = (float) 3.5; // OK; we're using a cast here.
or, alternatively, force the constant on the right-hand side of the assignment statement to be treated as a float by using the suffix "F", as shown here:
float y = 3.5F; // OK, because we're indicating that the constant is to be // treated as a float, not as a double.
Yet another option would be to simply use double rather than float variables to represent floating point numeric values.We'll typically use doubles instead of floats whenever we need to declare floating point variables in our SRS application, just to avoid these hassles of type conversion.
The only C# simple type that can't be cast, either implicitly or explicitly, into another type is the bool type.
You'll see other applications of casting, involving objects, later in the book.