C#, like most programming languages, has several built-in data types such as integer, string, and boolean. These classifications determine the range of values a variable of that type can hold, how the data will be stored, and what can be done with the data.
Plus Operator and Numeric Types vs. String
As an example of how the type classification can impact what can be done with data, let's look at how the + ("plus") operator works differently with built-in numeric types (such as an integer) than it does with strings. If you use the + operator with two strings, the result will be the same two strings shown side-by-side. They have been "added together" in the sense that the current values are shown together.
//C# code example of + with strings string x = "1"; string y = "2"; WriteLine($"x + y = {x + y}");
In a command-line application, the above statements result in something like:
The plus operator concatenates the two string values and we see 12 printed to the console.
//C# code example of + with integers int a = 1; int b = 2; WriteLine($"a + b = {a + b}");
In contrast, the same operator used with integers (whole numbers) will produce the sum of those two values;
Try It!
Read through the code below. Do you know what the result of running it would be?
int a = 1; int b = 2; string x = "1"; string y = "2"; WriteLine($"x + b = {x + b}");
Check Your Answer
If you guessed that "x + b = 12" would be written to the screen, you are correct!
C# is Static Typed at Compile Time
C# is statically typed at compile time. Once you declare a variable, it cannot be declared again or assigned a different type without a conversion. Those familiar with looser or dynamically typed languages may be surprised at how strict the rules can be in C#.
//C# code example (produces an error) int a = 1; a = "1";
In the above code example, the variable named 'a' is initially declared as an integer. The value can not be changed to a string in the next line without an error unless you explicitly change the type.
C# Type conversions are either implicit or explicit.
- Implicit conversion: No data is lost (the conversion is type-safe), and no additional code or syntax is required.
- Explicit conversion (cast): Data may be lost in the conversion, or there might be other issues in moving data from one type to another. A cast expression is required.
Type Conversion and Coffee (An Analogy)
Imagine that you have a full 12 oz cup of coffee that you want to pour into a different cup. The new cup happens to be 20 oz.
What will happen?
It doesn't matter how much coffee is in the 12 oz cup. All of it will fit in the 20 oz cup. Transferring from the smaller cup to the larger one, you won't lose any significant amount of coffee, right?
Implicit Casting
Imagine that instead of pouring coffee between two containers, we are moving data between two different variable types.
The coffee scenario (12 oz to a 20 oz cup) is similar to implicit casting; the destination can hold all the data, and there should be no data loss. Implicit casting doesn't require special syntax or code and is called a type conversion.
//Coffee Example: integer and double
int TwelveOunceCup = 12; double TwentyOunceCup = 0; TwentyOunceCup = TwelveOunceCup;
- The integer data type in C# represents a 32-bit number, and in this code example, it is being used to represent a smaller cup of coffee.
- In contrast, the double data type in C# represents a double-precision 64-bit number.
Following the analogy, by moving the contents of a smaller cup to a larger one (from an integer to a double), there would be no data loss.
Explicit Casting
What if the coffee cup sizes were reversed, and you need to move from a 20 oz cup to a 12 oz cup?
A full 20 oz cup poured into a 12oz cup would result in about 8 oz of coffee lost. If you are okay with that, or if you know that the 20 oz cup isn't full and the remaining coffee will fit in the smaller cup, then no problem.
However, to keep as much coffee as possible another solution is needed.
This second scenario (20 oz to 12 oz) is similar to explicit casting in that there is a possible loss of data.
Use explicit casting in C# to let the compiler know that although there is a possibility that data can be lost, it is okay. We are certain that the data will fit, or it won't matter if there is some data loss.
In the code example below, an int is a 12 oz cup, and a double is a 20 oz cup.
//Coffee Example 2: produces an error
int TwelveOunceCup = 0; double TwentyOunceCup = 20; TwelveOunceCup = TwentyOunceCup;
The error says it cannot implicitly convert from a double to an int. It recommends using a cast for an explicit conversion.
To go back to our coffee analogy, imagine the computer is worried you will be losing coffee by going from a 20 oz to a 12 oz cup. It's saying to you that there is a difference in cup sizes, and you need to be sure that you won't lose a drop of data.
In the following example, the double is cast as an integer and there is no error. The compiler is satisfied that you are taking responsibility for any loss of data.
//Coffee Example 3 int TwelveOunceCup = 0; double TwentyOunceCup = 20; TwelveOunceCup = (int)TwentyOunceCup;
MSDN Example (Fahrenheit to Celsius)
This operator converts from a class called Fahrenheit to a class called Celsius:
// Must be defined inside a class called Fahrenheit: public static explicit operator Celsius(Fahrenheit fahr) { return new Celsius((5.0f / 9.0f) * (fahr.degrees - 32)); } Fahrenheit fahr = new Fahrenheit(100.0f); Console.Write("{0} Fahrenheit", fahr.Degrees); Celsius c = (Celsius)fahr;
C# Predefined Integral Types
C# type/keyword | Range | Size | .NET type |
---|---|---|---|
sbyte |
-128 to 127 | Signed 8-bit integer | System.SByte |
byte |
0 to 255 | Unsigned 8-bit integer | System.Byte |
short |
-32,768 to 32,767 | Signed 16-bit integer | System.Int16 |
ushort |
0 to 65,535 | Unsigned 16-bit integer | System.UInt16 |
int |
-2,147,483,648 to 2,147,483,647 | Signed 32-bit integer | System.Int32 |
uint |
0 to 4,294,967,295 | Unsigned 32-bit integer | System.UInt32 |
long |
-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 | Signed 64-bit integer | System.Int64 |
ulong |
0 to 18,446,744,073,709,551,615 | Unsigned 64-bit integer | System.UInt64 |
C# supports two floating point types: float
and double
, both with 32-bit single-precision.
- The
float
type can represent values ranging from approximately1.5 * 10^-45
to3.4 * 10^38
with a precision of 7 digits. - The
double
type can represent values ranging from approximately5.0 * 10^-324
to1.7 × 10^308
with a precision of 15-16 digits.
(see more about data types at microsoft.com)