
Declaring variables
All applications process data. Data comes in, data is processed, and data goes out.
Data usually comes into our program from files, databases, or user input. Data can be put temporarily in variables that will be stored in the memory of the running program. When the program ends, the data in memory is lost. Data is usually output to files and databases or to the screen or a printer.
When using variables, you should think about, first, how much space it takes in memory, and, next, how fast it can be processed.
We control this by picking an appropriate type. You can think of simple common types such as int
and double
as being differently sized storage boxes. A smaller box would take less memory but may not be processed as quickly.
Naming variables
There are naming conventions for variables and it is best practice to follow them, as shown in the following table:

The following code block shows an example of declaring and initializing a local variable. Note that you can output the name of a variable using a keyword introduced in C# 6, that is, nameof
:
double heightInMetres = 1.88; Console.WriteLine($"The variable {nameof(heightInMetres)} has the value {heightInMetres}.");
Storing text
For text, a single letter such as A is stored as a char
type and is assigned using single-quotes around the literal value.
char letter = 'A';
Multiple characters like Bob
are stored as a string
type and are assigned using double quotes around the literal value:
string name = "Bob";
Storing numbers
Numbers are data that we want to perform an arithmetic calculation on (for example, multiplying).
Tip
A telephone number is not really a number. To decide whether a variable needs to be stored as a number or not, ask yourself whether you need to multiply two telephone numbers together or whether the number includes special characters such as (414)-555-1234. In these cases, the number is really a sequence of characters so should be stored as a string.
Numbers can be natural numbers, such as 42, used for counting (also called whole numbers), they can also be negative numbers, such as -42 (called integers), or they can be real numbers, such as 3.9 (with a fractional part), which are called single or double-precision floating point numbers in computing.
You might know that computers store everything as bits. A bit is either 0 or 1. This is called a binary number system. Humans use a decimal number system.
Storing whole numbers
The following table shows how computers store the number 10. Note the 1 bits in the 8 and the 2 columns; 8 + 2 = 10.

So, 10
in decimal is 00001010
in binary.
Computers can always exactly represent integers (positive and negative whole numbers) using the int
type or one of its sibling types such as short
.
Storing real numbers
Computers cannot always exactly represent floating point numbers. The float
and double
types store real numbers using single and double precision floating points.
The following table shows how a computer stores the number 12.75
. Note the 1 bits in the 8, 4, ½, and ¼ columns.
8 + 4 + ½ + ¼ = 12¾ = 12.75.

So, 12.75
in decimal is 00001100.1100
in binary.
As you can see, the number 12.75 can be exactly represented using bits. But some numbers can't, as you will see shortly.
Sizes of numbers in memory
In Visual Studio, click on File | Add | New Project…. In the Add New Project dialog, in the Installed Templates list, select Visual C#. In the list at the center, select Console Application, type the name Ch02_Numbers, and then click on OK.
In the Solution Explorer window, right-click on the solution and select Properties or press Alt + Enter. For Startup Project, select Current selection. From now on you can simply click on a project in the Solution Explorer and then press Ctrl + F5 to save, compile, and run that project.

Type the following code inside the Main
method:
Console.WriteLine($"int uses {sizeof(int)} bytes and can store numbers in the range {int.MinValue:N0} to {int.MaxValue:N0}."); Console.WriteLine($"double uses {sizeof(double)} bytes and can store numbers in the range {double.MinValue:N0} to {double.MaxValue:N0}."); Console.WriteLine($"decimal uses {sizeof(decimal)} bytes and can store numbers in the range {decimal.MinValue:N0} to {decimal.MaxValue:N0}.");
Press Ctrl + F5 and view the output in the console:
int uses 4 bytes and can store numbers in the range -2,147,483,648 to 2,147,483,647. double uses 8 bytes and can store numbers in the range -179,769,313,486,232,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 to 179,769,313,486,232,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000. decimal uses 16 bytes and can store numbers in the range -79,228,162,514,264,337,593,543,950,335 to 79,228,162,514,264,337,593,543,950,335.
Note that an int
variable uses four bytes of memory and can store positive or negative numbers up to about 2 billion.
A double
variable uses eight bytes of memory and can store much bigger values! A decimal
variable uses 16 bytes of memory and can store big numbers, but not as big as a double
.
Why might a double
variable be able to store bigger numbers than a decimal
variable yet use half the space in memory? Let's find out!
Comparing double and decimal
In Visual Studio, click on File | Add | New Project…. In the Add New Project dialog, in the Installed Templates list, select Visual C#. In the list at the center, select Console Application, type the name Ch02_NumberAccuracy, and then click on OK.
Enter the following code. Do not worry about understanding the syntax right now, although it isn't too hard to follow:
double a = 0.1; double b = 0.2; if (a + b == 0.3) { Console.WriteLine($"{a} + {b} equals 0.3"); } else { Console.WriteLine($"{a} + {b} does NOT equal 0.3"); }
Press Ctrl + F5 and view the output in the console:
0.1 + 0.2 does NOT equal 0.3
The double
type is NOT guaranteed to be accurate. Only use double
when accuracy, especially when comparing two numbers, is not important, for example, when measuring a person's height.
The problem with the preceding code is how the computer stores the number 0.1 or multiples of 0.1. To represent 0.1 in binary, the computer stores 1 in the 1/16 column, 1 in the 1/128 column, 1 in the 1/1024 column, and so on. The number 0.1
in decimal is 0.0001001001001
repeating forever:

Tip
Never compare double values using ==
. During the First Gulf War, an American patriot missile battery used double
values in its calculations. The inaccuracy caused it to fail to track and intercept an incoming Iraqi Scud missile, and 28 soldiers were killed, as you can read about at this link: https://www.ima.umn.edu/~arnold/disasters/patriot.html.
Copy and paste the code you wrote before that used doubles and then modify it to look like the following code:
decimal c = 0.1M; // M indicates a decimal literal value decimal d = 0.2M; if (c + d == 0.3M) { Console.WriteLine($"{c} + {d} equals 0.3"); } else { Console.WriteLine($"{c} + {d} does NOT equal 0.3"); }
Press Ctrl + F5 and view the output in the console:
0.1 + 0.2 equals 0.3
The decimal
type is accurate because it actually stores the number as a large integer and shifts the decimal point. For example, 0.1 is stored as 1 with a note to shift the decimal point one place to the left. 12.75 is stored as 1275 with a note to shift the decimal point two places to the left.
Tip
Best Practice
Use int
for whole numbers and double
for real numbers. Use decimal
for money, CAD drawings, general engineering, and wherever accuracy of a real number is important.
The double
type has some useful special values: double.NaN
means not-a-number and double.Infinity
means an infinitely large value. You can use these special values when comparing the value of double
variables.
Storing Booleans
Booleans (bool
) can only contain one of the two values: true
or false
, as shown in the following code. They are most commonly used to branch and loop, as you will see in Chapter 3, Controlling the Flow, Converting Types, and Handling Exceptions:
bool happy = true; bool sad = false;
The object type
There is a special type named object
that can store any type of data, but its flexibility comes at the cost of messier code and poor performance due to boxing and unboxing operations when storing a value type. You should avoid it whenever possible.
Add a new Console Application project named Ch02_SpecialTypes and add the following code to the Main
method:
object height = 1.88; // storing a double in an object object name = "Amir"; // storing a string in an object int length1 = name.Length; // gives compile error! int length2 = ((string)name).Length; // cast to access members
The object
type has been available since the first version of C# but C# 2 and higher versions have better alternatives, which we will cover later, that provide the flexibility we want without the performance overhead.
The dynamic type
There is another special type named dynamic
that can also store any type of data, and, like object
, its flexibility comes at the cost of performance. Unlike object
, the value stored in the variable can have its members invoked without an explicit cast, as shown in the following code:
dynamic anotherName = "Ahmed"; // storing a string in a dynamic object int length = anotherName.Length; // this compiles but might throw an exception at run-time!
The limitation of dynamic
is that Visual Studio cannot show IntelliSense to help you write the code because the compiler doesn't check at build time. Instead, the CLR checks for the member at runtime. The dynamic
keyword was introduced in C# 4.
Local variables
Local variables are declared inside methods and they only exist during the call to that method. Once the method returns, the memory allocated to any local variables is released.
Add a new Console Application project named Ch02_Variables. Enter the following code to declare and assign values to some local variables inside the Main
method. Note that we specify the type before the name of each variable:
int population = 66000000; double weight = 1.88; // in kilograms decimal price = 4.99M; // in pounds sterling string fruit = "Apples"; // strings use double-quotes char letter = 'Z'; // chars use single-quotes
Tip
Visual Studio 2015 will show green squiggles under each of the variable names to warn you that the variable is assigned but its value is never used.
Inferring the type of a local variable
You can use the var
keyword to declare local variables. The compiler will infer the type from the literal value you assign after the assignment =
operator.
A literal number without a decimal point is inferred as an int
variable unless you add the L
suffix, in which case it infers a long
variable. A literal number with a decimal point is inferred as a double
unless you add the M
suffix, in which case it infers a decimal
variable, or the F suffix, in which case it infers a float
variable. Double quotes indicate a string
variable, single quotes indicate a char
, and the true
and false
values indicates a bool
.
Modify your code to use var
:
var population = 66000000; var weight = 1.88; // in kilograms var price = 4.99M; // in pounds sterling var fruit = "Apples"; // strings use double-quotes var letter = 'Z'; // chars use single-quotes var happy = true;
Tip
Although using var
is convenient, some developers avoid using it to make it easier for a code reader to understand the types in use in the code. Personally, I use it whenever the type is obvious. For example, the first statement is just as clear as the second in stating what the type of the xml
variable is but is shorter than the second statement:
var xml = new XmlDocument(); XmlDocument xml = new XmlDocument();
Making a value type nullable
Most of the primitive types except string
are value types. This means they must have a value. You can determine the default value of a type using the default()
operator. The default value of an int
variable is 0
(zero):
int defaultValueOfInt = default(int); // 0
Strings are reference types. This means that they can have a null
value. The null
value is a special value that indicates that the variable does not reference anything (yet).
Sometimes it is convenient to allow a value type to be null
. You can do this by adding a question mark as a suffix to the type when declaring a variable, as shown in the following code:
int ICannotBeNull = 4; ICannotBeNull = default(int); // 0 int? ICouldBeNull = null; int result1 = ICouldBeNull.GetValueOrDefault(); // 0 ICouldBeNull = 4; int result2 = ICouldBeNull.GetValueOrDefault(); // 4
Storing multiple values in an array
When you need to store multiple values of the same type, you can declare an array. For example, you might need to store four names in a string array.
Add the following lines of code to the end of the Main
method. It declares an array for storing four strings. Then, it stores strings at index positions 0
to 3
(note that arrays count from zero, so the last item is one less than the length of the array). Finally, it loops through each item in the array using a for
statement that we cover in more detail in Chapter 3, Controlling the Flow, Converting Types, and Handling Exceptions:
// declaring the size of the array string[] names = new string[4]; // storing items at index positions names[0] = "Kate"; names[1] = "Jack"; names[2] = "Rebecca"; names[3] = "Tom"; for (int i = 0; i < names.Length; i++) { Console.WriteLine(names[i]); // read the item at this index }
Tip
Arrays are always of a fixed size, so you need to decide how many items you want to store before instantiating them. Arrays are useful for temporarily storing multiple items, but collections are more flexible when adding and removing items dynamically. We cover collections in Chapter 4, Using Common .NET Types.