Type Conversion
Programs constantly move values between types: an int into a double calculation, a number typed by the user as text into an int, a price into a string for display. C# does safe conversions automatically and makes you ask explicitly for anything that could lose information.
Implicit conversions
When a conversion can never lose data — such as int to long, or int to double — C# does it automatically. These are called widening conversions:
int count = 42; long bigger = count; double asDouble = count; decimal money = count; Console.WriteLine($"{bigger} {asDouble} {money}");
42 42 42
Explicit conversions (casts)
Going the other way could lose information, so the compiler refuses unless you write a cast — the target type in parentheses:
double price = 9.99; int whole = price;
Program.cs(2,13): error CS0266: Cannot implicitly convert type 'double' to 'int'. An explicit conversion exists (are you missing a cast?)
double price = 9.99; int whole = (int)price; // fraction is dropped, not rounded Console.WriteLine(whole); long large = 3_000_000_000; int truncated = (int)large; // doesn't fit: bits are cut off Console.WriteLine(truncated); double ratio = 7 / 2; // integer division happens first! double correct = (double)7 / 2; Console.WriteLine($"{ratio} vs {correct}");
9 -1294967296 3 vs 3.5
A cast is you telling the compiler "I know this might lose data". Casting a double to int truncates towards zero; use Math.Round first if you want rounding.
Converting to strings
Every value has ToString(), and string interpolation calls it for you. You can pass a format string to control the result — lesson 18 covers formats in depth:
int n = 255; double d = 1234.5678; Console.WriteLine(n.ToString()); Console.WriteLine(n.ToString("X")); // hexadecimal Console.WriteLine(d.ToString("F2")); // 2 decimal places Console.WriteLine(true.ToString()); Console.WriteLine("Value: " + n); // + with a string converts automatically
255 FF 1234.57 True Value: 255
Parsing strings
To turn text into a number, use the type's Parse method. If the text isn't a valid number, Parse throws a FormatException:
int age = int.Parse("42"); double temp = double.Parse("-3.5"); bool ok = bool.Parse("true"); Console.WriteLine(age + 1); Console.WriteLine(temp * 2); Console.WriteLine(ok); int bad = int.Parse("forty-two");
43 -7 True Unhandled exception. System.FormatException: The input string 'forty-two' was not in a correct format.
TryParse: parsing safely
For input that might be invalid — anything a user types, or data from a file — use TryParse. It returns true or false instead of throwing, and hands back the number through an out variable (lesson 22):
string[] inputs = ["120", "12.5", "abc", " 7 ", ""]; foreach (string text in inputs) { if (int.TryParse(text, out int value)) { Console.WriteLine($"'{text}' -> {value}"); } else { Console.WriteLine($"'{text}' is not a whole number"); } }
'120' -> 120 '12.5' is not a whole number 'abc' is not a whole number ' 7 ' -> 7 '' is not a whole number
TryParse is the pattern you'll use most often. Notice that surrounding spaces are allowed.
Culture matters
Parsing and formatting use the computer's current culture. In much of Europe the decimal separator is a comma, so double.Parse("3.5") gives a different answer there. For data files, network protocols and anything not shown to a user, pass CultureInfo.InvariantCulture so results are the same everywhere:
using System.Globalization; var german = new CultureInfo("de-DE"); double value = 1234.5; Console.WriteLine(value.ToString(german)); Console.WriteLine(value.ToString(CultureInfo.InvariantCulture)); Console.WriteLine(double.Parse("3,75", german)); Console.WriteLine(double.Parse("3.75", CultureInfo.InvariantCulture));
1234,5 1234.5 3.75 3.75
The Convert class
Convert offers conversions between many types. Unlike a cast, Convert.ToInt32 rounds a double (using banker's rounding), and it treats null as zero:
Console.WriteLine(Convert.ToInt32(7.6)); Console.WriteLine(Convert.ToInt32(6.5)); Console.WriteLine(Convert.ToInt32("15")); Console.WriteLine(Convert.ToBoolean(1)); Console.WriteLine(Convert.ToString(255, 2)); // binary text Console.WriteLine(Convert.ToInt32("ff", 16)); // from hexadecimal
8 6 15 True 11111111 255
Characters and numbers
char c = 'A'; int code = c; // implicit: char -> int char back = (char)(code + 2); // explicit: int -> char char digit = '7'; int digitValue = digit - '0'; // the classic trick int viaMethod = (int)char.GetNumericValue(digit); Console.WriteLine($"{code} {back} {digitValue} {viaMethod}");
65 C 7 7
Try it yourself
Total up the valid numbers in the array and count the invalid ones.
Sum: 47, invalid entries: 2