C# is a statically typed language. This means that if you declare a variable as an int, the compiler won’t let you put a string or a bool into it “just because”.
However, sometimes we need to move data from one type to another. Maybe you have an int and need to use it in a mathematical operation that requires a double. Or you have a double and need to save it in a field that only accepts int.
This is where numeric conversions come into play. C# offers two main types of numeric conversions:
- Implicit conversions: These conversions do not require special notation and are safe, as they do not cause data loss.
- Explicit conversions (casting): These conversions require the use of a conversion operator and can lead to data loss if not handled carefully.
Implicit Conversions (Widening)
Implicit conversions are those that the C# compiler performs automatically. You don’t need to write any special code.
Why do they happen? Because they are safe conversions.
The general rule is “Widening”: If you try to store a small value in a large container, there’s no risk of overflow. No information is lost.
int smallNumber = 1234;
long largeNumber = smallNumber; // Implicit Conversion: OK
float height = 1.75f;
double preciseHeight = height; // Implicit Conversion: OK
In these cases:
- An
int(32 bits) fits perfectly into along(64 bits). - A
float(less precision) fits into adouble(greater precision).
Explicit Conversions (Casting)
Explicit conversions are those where we force the compiler to perform the conversion, even if there is risk. This is commonly known as Casting.
This happens in “Narrowing” operations: trying to put a value from a large container into a small one.
To perform a cast, we place the target type in parentheses (type) in front of the variable.
double exactPrice = 99.99;
int integerPrice = (int)exactPrice; // Explicit Casting
Console.WriteLine(integerPrice); // Prints: 99
When casting from a decimal (double, float, decimal) to an integer, C# TRUNCATES the number. It does not round to the nearest. It simply removes everything after the decimal point.
Numeric Conversions Table
To have it clear visually, here is a simplified table of which conversions are implicit. If it’s not on the list, assume you need an explicit Cast.
| From | Implicitly converts to |
|---|---|
sbyte | short, int, long, float, double, decimal |
byte | short, ushort, int, uint, long, ulong, float, double, decimal |
short | int, long, float, double, decimal |
int | long, float, double, decimal |
long | float, double, decimal |
float | double |
Notice that there are no implicit conversions to char, byte, or short from other numeric types (except for small constant literals). They always require casting.
Conversion using methods of the Convert class
C# includes the Convert class, which provides static methods for performing conversions between data types.
double doubleValue = 150.75;
int intValue = Convert.ToInt32(doubleValue); // Automatically rounds the value
The Convert.ToInt32() method rounds the value of doubleValue instead of truncating it, which can be useful in applications where precision is required.
Some common conversion methods include:
Convert.ToDouble()Convert.ToInt32()Convert.ToDecimal()
Convert performs rounding, and also handles null values by returning 0 (instead of crashing), which is very useful when working with data from databases or web forms.
Numeric conversions from text strings
For many applications, we need to convert numeric values to text to display them in a user interface, or convert text to numeric values from user input.
In C#, this is done mainly with the ToString(), Parse(), and TryParse() methods.
Convert from number to string
The ToString() method converts a number to a string. We can specify formats to represent the number according to our needs:
double doubleValue = 12345.6789;
string text = doubleValue.ToString("F2"); // Converts to "12345.68" with two decimals
Convert from string to number
To convert a text string to a number, we use Parse() or TryParse():
Converts a string to a numeric type, but throws an exception if the conversion fails.
string text = "123.45";
double doubleValue = double.Parse(text);
Similar to Parse, but instead of throwing an exception, it returns false if the conversion is not possible, avoiding runtime errors.
string text = "123.45";
if (double.TryParse(text, out double doubleValue))
{
Console.WriteLine($"Successful conversion: {doubleValue}");
}
else
{
Console.WriteLine("Conversion error");
}
TryParse is preferable when the input may not be numeric, as it allows for safer error handling.
Practical Examples
Unit Conversion
To illustrate numeric conversion in C#, we will develop a program that converts kilometers to miles. This involves converting between data types to ensure calculations are accurate and handled correctly.
using System;
public class UnitConverter
{
public static void Main()
{
Console.Write("Enter distance in kilometers: ");
string input = Console.ReadLine();
if (double.TryParse(input, out double kilometers))
{
double miles = ConvertKilometersToMiles(kilometers);
Console.WriteLine($"{kilometers} kilometers equals {miles:F2} miles.");
}
else
{
Console.WriteLine("Please enter a valid numeric value.");
}
}
public static double ConvertKilometersToMiles(double kilometers)
{
double conversionFactor = 0.621371;
return kilometers * conversionFactor;
}
}
This example converts a distance entered in kilometers to miles, using TryParse to validate the input. The output is displayed with two decimals using the "F2" format in ToString().
