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:

C#
int count = 42;
long bigger = count;
double asDouble = count;
decimal money = count;

Console.WriteLine($"{bigger} {asDouble} {money}");
Output
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:

C#
double price = 9.99;
int whole = price;
Build error
Program.cs(2,13): error CS0266: Cannot implicitly convert type 'double' to 'int'. An explicit conversion exists (are you missing a cast?)
C#
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}");
Output
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:

C#
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
Output
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:

C#
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");
Output
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):

C#
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");
    }
}
Output
'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:

C#
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));
Output
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:

C#
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
Output
8
6
15
True
11111111
255

Characters and numbers

C#
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}");
Output
65 C 7 7

Try it yourself

Total up the valid numbers in the array and count the invalid ones.

Try it yourself · Program.cs
Edit the code, copy it into Program.cs and run it with dotnet run Program.cs (.NET 10 or later). How to set up .NET
Output
Sum: 47, invalid entries: 2