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, second, 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 different size storage boxes. A smaller box would take less memory but may not be as fast at being processed. Some of these boxes may be stacked close by, and some may be thrown into a big heap further away.

Naming variables

There are naming conventions for variables, and it is good practice to follow them, as shown in the following table:

Naming convention

Examples

Use when naming

Camel case

cost, orderDetail, dateOfBirth

Local variables and private members.

Pascal/title case

Cost, OrderDetail, DateOfBirth

Type names and non-private members.

Tip

Good Practice

Following a consistent set of naming conventions will enable your code to be easily understood by other developers (and yourself in the future!) Naming Guidelines: https://msdn.microsoft.com/en-us/library/ms229002(v=vs.110).aspx

The following code block shows an example of declaring and initializing a local variable by assigning a value to it. Note that you can output the name of a variable using a keyword introduced in C# 6, that is, nameof:

    // let the height variable become equal to the value 1.88 
    double heightInMetres = 1.88; 
    Console.WriteLine($"The variable {nameof(heightInMetres)} has the
    value {heightInMetres}."); 

Note

The message in double quotes in the preceding code wraps onto a second line because the width of a printed page is too narrow. When entering a statement like this in your code editor, type it all in a single line.

Literal values

When you assign to a variable, you often assign a literal value. A literal is notation that represents a fixed value. Data types have different notations for their literal values.

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'; 

For text, multiple letters, such as 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.

Note

A telephone number is not a number. To decide whether a variable should 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 a sequence of characters, so it 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.

    int myIntegerNumber = 23; 
    double myRealNumber = 2.3; 

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.

Note

The decimal number system has ten as its base. Although it is the number base most commonly used by human civilizations, other number-base systems are popular in science, engineering, and computing.

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:

128

64

32

16

8

4

2

1

0

0

0

0

1

0

1

0

So, 10 in decimal is 00001010 in binary.

C# 7 improvements

Two of the improvements in C# 7 are the use of the underscore character (_) as a digit separator and support for binary literals.

You can insert underscores anywhere into a number literal, including decimal, binary, or hexadecimal notation to improve legibility. For example, you could write the value for one million in decimal notation (Base 10) as: 1_000_000.

To use binary notation (Base 2), using only 1s and 0s, start the number literal with 0b. To use hexadecimal notation (Base 16), using 0 to 9 and A to F, start the number literal with 0x, as shown in the following code:

    int decimalNotation = 2_000_000; // 2 million 
    int binaryNotation = 0b_0001_1110_1000_0100_1000_0000; // 2 million 
    int hexadecimalNotation = 0x_001E_8480; // 2 million 

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.

128

64

32

16

8

4

2

1

.

½

¼

1/8

1/16

0

0

0

0

1

1

0

0

.

1

1

0

0

So, 12.75 in decimal is 00001100.1100 in binary.

As you can see, the number 12.75 can be exactly represented using bits. However, some numbers can't, as you will see shortly.

Using Visual Studio 2017

In Visual Studio 2017, 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 App (.NET Core), 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, as shown in the following screenshot:

Using Visual Studio 2017

Using Visual Studio Code

Create a new folder inside the Chapter02 folder named Ch02_Numbers.

In Visual Studio Code, open the Ch02_Numbers folder and use the Integrated Terminal to create a new console application using the command dotnet new console. When you open the Program.cs file, you will be prompted to restore packages.

Writing code to explore numbers

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}.");

Note

Remember to enter the statements that use double-quotes in a single line.

Run the console application by pressing Ctrl + F5, or entering dotnet run, and view the output:

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,0 00,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,00 0,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,0 00,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,0 00,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,00 0,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,0 00,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

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

Under the previous statements, 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"); 
    } 

Run the console application and view the output:

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:

4

2

1

.

½

¼

1/8

1/16

1/32

1/64

1/128

1/256

1/512

1/1024

1/2048

0

0

0

.

0

0

0

1

0

0

1

0

0

1

0

Tip

Good Practice

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; you can read about this at: https://www.ima.umn.edu/~arnold/disasters/patriot.html

Copy and paste the code you wrote before that used double variables 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"); 
    } 

Run the console application and view the output:

0.1 + 0.2 equals 0.3

The decimal type is accurate because it 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

Good 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, double.Epsilon is the smallest positive number that can be stored in a double, and double.Infinity means an infinitely large value. You can use these special values when comparing double values.

Storing Booleans

Booleans 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.

Note

From now on, I will assume that you know how to create a new console application using either Visual Studio 2017 or Visual Studio Code so I will only give general instructions.

Add a new console application project named Ch02_Variables 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 a better alternative called generics, 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:

    // storing a string in a dynamic object 
    dynamic anotherName = "Ahmed";  
    // this compiles but might throw an exception at run-time! 
    int length = anotherName.Length;  

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.

Note

Strictly speaking, value types are released while reference types must wait for a garbage collection. You will learn about the difference between value types and reference types later.

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 = 66_000_000; // 66 million in UK 
    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 
    bool happy = true; // Booleans have value of true or false 

Note

Visual Studio 2017 and Visual Studio Code 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 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 variable, and the true and false values infer a bool.

Modify your code to use var:

    var population = 66_000_000; // 66 million in UK 
    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; // Booleans have value of true or false 

Tip

Good Practice

Although using var is convenient, smart developers avoid using it, to make it easier for a code reader to understand the types in use. Personally, I use it only when the type is obvious. For example, in the following code statements, the first statement is just as clear as the second in stating what the type of the xml variable is, but it is shorter. However, the third statement isn't clear, so the fourth is better. If in doubt, spell it out!

    // good use of var 
    var xml1 = new XmlDocument(); 
    // unnecessarily verbose repeating XmlDocument 
    XmlDocument xml2 = new XmlDocument(); 
 
    // bad use of var; what data type is file1? 
    var file1 =
      File.CreateText(@"C:something.txt"); 
    // good use of a specific type declaration 
    StreamWriter file2 = 
      File.CreateText(@"C:something.txt"); 

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):

    Console.WriteLine($"{default(int)}"); // 0 
    Console.WriteLine($"{default(bool)}"); // False 
    Console.WriteLine($"{default(DateTime)}"); // 1/01/0001 00:00:00 

Strings are reference types. This means that they contain the memory address of a variable, not the value of the variable itself. A reference type variable can have a null value. The null value is a special literal value that indicates that the variable does not reference anything (yet).

Note

You will learn more about value types and reference types in Chapter 7, Implementing Interfaces and Inheriting Classes.

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; 
    int? ICouldBeNull = null; 
    Console.WriteLine(ICouldBeNull.GetValueOrDefault()); // 0 
    ICouldBeNull = 4; 
    Console.WriteLine(ICouldBeNull.GetValueOrDefault()); // 4  

Checking for null

It is important to check if a reference type or nullable value type variable currently contains null because if you do not, a NullReferenceException can be thrown causing an error in your code.

    // check is myVariable is not null before using it 
    if (ICouldBeNull != null) 
    { 
      // do something with ICouldBeNull 
    } 

If you are trying to get a field or property from a variable that might be null, use the null check operator (?.), as shown in the following code:

    string authorName = null; 
    // if authorName is null, instead of throwing an exception, 
    // null is returned 
    int? howManyLetters = authorName?.Length; 

Sometimes you want to either assign a variable to a result, or use an alternative value, such as zero, if the variable is null. You do this using the null-coalescing operator (??), as shown in the following code:

    // result will be three if howManyLetters is null 
    var result = howManyLetters ?? 3; 
    Console.WriteLine(result); 

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.

The following code declares an array for storing four string values. Then, it stores string values at index positions 0 to 3 (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 will cover in more detail in Chapter 3, Controlling the Flow, Converting Types, and Handling Exceptions.

Add the following lines of code to the end of the Main method:

    // 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 
    } 

Note

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 will cover collections in Chapter 4, Using .NET Standard Types.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.128.200.220