Storing Information with Variables in C#

This is Day 3, "Storing Information with Variables," from Sams Teach Yourself C# in 21 Days. More information about the book appears at the end of this chapter.

When you start writing programs, you'll quickly find that you need to keep track of different types of information. This might be the tracking of your clients' names, the amounts of money in your bank accounts, or the ages of your favorite movie stars. To keep track of this information, your computer programs need a way to store the values. In this sample chapter, you'll learn what a variable is, as well as how to: create variable names in C#, use different types of numeric variables, evaluate the differences and similarities between character and numeric values, and declare and initialize variables.

Variables

A variable is a named data storage location in your computer's memory. By using a variable's name in your program, you are, in effect, referring to the information stored there. For example, you could create a variable called my_variable that holds a number. You would be able to store different numbers in the my_variable variable.

You could also create variables to store information other than a simple number. You could create a variable called BankAccount to store a bank account number, a variable called email to store an email address, or a variable called address to store a person's mailing address. Regardless of what type of information will be stored, a variable is used to obtain its value.

Variable Names

To use variables in your C# programs, you must know how to create variable names. In C#, variable names must adhere to the following rules:

The name can contain letters, digits, and the underscore character (_).

The first character of the name must be a letter. The underscore is also a legal first character, but its use is not recommended at the beginning of a name. An underscore is often used with special commands, and it's sometimes hard to read.

Case matters (that is, upper- and lowercase letters). C# is case-sensitive; thus, the names count and Count refer to two different variables.

C# keywords can't be used as variable names. Recall that a keyword is a word that is part of the C# language. (A complete list of the C# keywords can be found in Appendix B, "C# Keywords.")

The following list contains some examples of valid and invalid C# variable names:

Variable Name

Legality

Percent

Legal

y2x5__w7h3

Legal

yearly_cost

Legal

_2010_tax

Legal, but not advised

checking#account

Illegal; contains the illegal character #

double

Illegal; is a C keyword

9byte

Illegal; first character is a digit

Because C# is case-sensitive, the names percent, PERCENT, and Percent are considered three different variables. C# programmers commonly use only lowercase letters in variable names, although this isn't required. Often, programmers use mixed case as well. Using all-uppercase letters is usually reserved for the names of constants (which are covered later today).

Variables can have any name that fits the rules listed previously. For example, a program that calculates the area of a circle could store the value of the radius in a variable named radius. The variable name helps make its usage clear. You could also have created a variable named x or even billy_gates; it doesn't matter. Such a variable name, however, wouldn't be nearly as clear to someone else looking at the source code. Although it might take a little more time to type descriptive variable names, the improvements in program clarity make it worthwhile.

Many naming conventions are used for variable names created from multiple words. Consider the variable name circle_radius. Using an underscore to separate words in a variable name makes it easy to interpret. Another style is called Pascal notation. Instead of using spaces, the first letter of each word is capitalized. Instead of circle_radius, the variable would be named CircleRadius. Yet another notation that is growing in popularity is Camel notation. Camel notation is like Pascal notation, except the first letter of the variable name is also lower case. A special form of Camel notation is called Hungarian notation. With Hungarian notation, you also include information in the name of the variable—such as whether it is numeric, has a decimal value, or is text—that helps to identify the type of information being stored. The underscore is used in this book because it's easier for most people to read. You should decide which style you want to adopt.

Note:

DO use variable names that are descriptive.

DO adopt and stick with a style for naming your variables.

DON'T name your variables with all capital letters unnecessarily.

Note:
C# supports a Unicode character set, which means that letters from any language can be stored and used. You can also use any Unicode character to name your variables.

Using Variables

Before you can use a variable in a C# program, you must declare it. A variable declaration tells the compiler the name of the variable and the type of information the variable will be used to store. If your program attempts to use a variable that hasn't been declared, the compiler will generate an error message.

Declaring a variable also enables the computer to set aside memory for it. By identifying the specific type of information that will be stored in a variable, you gain the best performance and avoid wasting memory.

Declaring a Variable

A variable declaration has the following form:

typename varname;

typename specifies the variable type. In the following sections you will learn about the types of variables that are available in C#. varname is the name of the variable. To declare a variable that can hold a standard numeric integer, you use the following line of code:

int my_number;

The name of the variable declared is my_number. The data type of the variable is int. As you will learn in the following section, the type int is used to declare integer variables, which is perfect for this example!

You can also declare multiple variables of the same type on one line by separating the variable names with commas. This enables you to be more concise in your listings. Consider the following line:

int count, number, start;

This line declares three variables: count, number, and start. Each of these variables is type int, which is for integers.

Note: Although declaring multiple variables on the same line can be more concise, I don't recommend that you always do this. There are times when it is easier to read and follow your code by using multiple declarations. There will be no noticeable performance loss by doing separate declarations.

Storing Information with Variables in C#

Assigning Values to Variables

Now that you know how to declare a variable it is important to learn how to store values. After all, the purpose of a variable is to store information!

The format for storing information in a variable is

varname = value;

You have already seen that varname is the name of the variable. value is the value that will be stored in the variable. For example, to store the number 5 in the variable, my_variable, you enter the following:

my_variable = 5;

To change the value, you simply reassign a new value:

my_variable = 1010;

Listing 3.1 illustrates assigning values to a variable. It also shows that you can overwrite a value.

Output

my_variable contains the value 5
my_variable contains the value 1010

Analysis

Enter this listing into your editor, compile it, and execute it. If you need a refresher on how to do this, refer to Day 1, "Getting Started with C#." The first three lines of this listing are comments. Lines 11, 14, and 18 also contain comments. Remember that comments provide information; the compiler will ignore them. Line 5 includes the System namespace which you need to do things such as writing information. Line 7 declares the class that will be your program (var_values). Line 9 declares the entry point for your program, the Main() function. Remember, Main() has to be capitalized or you'll get an error!

Line 12 is the beginning point of today's lesson. Line 12 declares a variable called my_variable of type integer (int). After this line has executed, the computer knows that a variable called my_variable exists and it enables you to use it. In line 15 you use this variable and assign the value of 5 to my_variable. In line 16 you use Console.WriteLine to display the value of my_variable. As you can see in the output, the value 5—which was assigned in line 15—is displayed. In line 19 you change the value of my_variable from 5 to 1010. You see that this new assignment worked because the call to Console.WriteLine in line 20 prints the new value 1010 instead of 5.

After you assign the value 1010 to my_variable in line 19, the value of 5 is gone. From that point, the program no longer knows that 5 ever existed.

Note: You must declare a variable before you can use it. A variable can, however, be declared at almost any place within a listing.

Setting Initial Values in Variables

You might be wondering whether you can assign a value to a variable at the same time you declare it. Yes, you definitely can. In fact, it is good practice to make sure you always initialize a variable at the time you declare it. To initialize my_variable to the value of 8 when you declare it, you combine what you've done before:

int my_variable = 8;

Any variable can be initialized when being declared using the following structure:

typename varname = value;

You can also declare multiple variables on the same line and assign values to each of them:

int my_variable = 8, your_variable = 1000;

This line declares two integer variables called my_variable and your_variable. my_variable is assigned the value of 8 and your_variable is assigned 1000. Notice that these declarations are separated by a comma and that the statement ends with the standard semicolon. Listing 3.2 shows this statement in action.

Output

Analysis

This listing declares and initializes two variables on line 12. The variable, my_variable, is initialized to the value of 8 and the variable, your_variable, is initialized to the value of 1000. Line 15 prints the value of my_variable so you can see what it contains. Looking at the output, you see that it contains the value 8, which was just assigned.

In line 18, the value of 5 is assigned to my_variable. Lines 21 and 22 print the final values of the two variables. The value of my_variable is printed as 5. The original value of 8 is gone forever! your_variable still contains its original value of 1000.

Using Uninitialized Variables

What happens if you try to use a variable without initializing it? Consider the following:

In this snippet of code, blank_variable is printed in the second line. What is the value of blank_variable? This variable was declared in the first line, but it was not initialized to any value. You'll never know what the value of blank_variable is because the compiler will not create the program. Listing 3.3 proves this.

Analysis

This program will not compile. Rather, the compiler will give you the following error:

blank.cs(13,67): error CS0165: Use of unassigned local
variable 'blank_variable'

C# will not let you use an uninitialized variable.

Note: In other languages, such as C and C++, this listing would compile. The value printed for the blank_variable in these other languages would be garbage. C# prevents this type of error from occurring.

Storing Information with Variables in C#

Understanding Your Computer's Memory

If you already know how a computer's memory operates, you can skip this section. If you're not sure, read on. This information is helpful to understanding programming.

What is your computer's RAM used for? It has several uses, but only data storage need concern you as a programmer. Data is the information with which your C# program works. Whether your program is maintaining a contact list, monitoring the stock market, keeping a budget, or tracking the price of snickerdoodles, the information (names, stock prices, expense amounts, or prices) is kept within variables in your computer's RAM when it is being used by your running program.

A computer uses random access memory (RAM) to store information while it is operating. RAM is located in integrated circuits, or chips, inside your computer. RAM is volatile, which means that it is erased and replaced with new information as often as needed. Being volatile also means that RAM "remembers" only while the computer is turned on and loses its information when you turn the computer off.

A byte is the fundamental unit of computer data storage. Each computer has a certain amount of RAM installed. The amount of RAM in a system is usually specified in megabytes (MB), such as 32MB, 64MB, 128MB or more. One megabyte of memory is 1,024 kilobytes (KB). One kilobyte of memory consists of 1,024 bytes. Thus, a system with 8MB of memory actually has 8_1,024KB, or 8,192KB of RAM. This is 8,192KB_1,024 bytes for a total of 8,388,608 bytes of RAM. Table 3.1 provides you with an idea of how many bytes it takes to store certain kinds of data.

Table 3.1: Minimum Memory Space Generally Required to Store Data

Data

Bytes Required

The letter x

2

The number 500

2

The number 241.105

4

The phrase Teach Yourself C#

34

One typewritten page

Approximately 4,000

The RAM in your computer is organized sequentially, one byte following another. Each byte of memory has a unique address by which it is identified—an address that also distinguishes it from all other bytes in memory. Addresses are assigned to memory locations in order, starting at 0 and increasing to the system limit. For now, you don't need to worry about addresses; it's all handled automatically.

Now that you understand a little about the nuts and bolts of memory storage, you can get back to C# programming and how C# uses memory to store information.

C# Data Types

You know how to declare, initialize, and change the values of variables; it is important that you know the data types you can use. You learned earlier that you have to declare the data type when you declare a variable. You've seen that the int keyword declares variables that can hold integers. An integer is simply a whole number that doesn't contain a fractional or decimal portion. The variables you've declared to this point hold only integers. What if you want to store other types of data, such as decimals or characters?

Numeric Variable Types

C# provides several different types of numeric variables. You need different types of variables, because different numeric values have varying memory storage requirements and differ in the ease with which certain mathematical operations can be performed on them. Small integers (for example, 1, 199, and -8) require less memory to store, and your computer can perform mathematical operations (addition, multiplication, and so on) with such numbers very quickly. In contrast, large integers and values with decimal points require more storage space and more time for mathematical operations. By using the appropriate variable types, you ensure that your program runs as efficiently as possible.

The following sections break the different numeric data types into four categories:

Integral

Floating-point

Decimal

Boolean

Earlier in today's lesson, you learned that variables are stored in memory. Additionally, you learned that different types of information required different amounts of memory. The amount of memory used to store a variable is based on its data type. Listing 3.4 is a program that contains code beyond what you know right now; however, it provides you with the amount of information needed to store some of the different C# data types.

You must include extra information for the compiler when you compile this listing. This extra information, referred to as a flag to the compiler, can be included on the command line. Specifically, you need to add the /unsafe flag as shown:

csc /unsafe sizes.cs

If you are using an integrated development environment, you need to set the unsafe option as instructed by its documentation.

Output

A byte is 1 byte(s)
An sbyte is 1 byte(s)
A char is 2 byte(s)
A short is 2 byte(s)
An ushort is 2 byte(s)
An int is 4 byte(s)
An uint is 4 byte(s)
A long is 8 byte(s)
An ulong is 8 byte(s)
A float is 4 byte(s)
A double is 8 byte(s)
A decimal is 16 byte(s)
A boolean is 1 byte(s)

Analysis

Although you haven't learned all the data types yet, I believed it valuable to present this listing here. As you go through the following sections, refer to this listing and its output.

This listing uses a C# keyword called sizeof. The sizeof keyword tells you the size of a variable. In this listing, sizeof is used to show the size of the different data types. For example, to determine the size of an int, you can use:

sizeof(int)

If you had declared a variable called x, you could determine its size—which would actually be the size of its data type - by using the following code:

sizeof(x)

Looking at the output of Listing 3.4, you see that you have been given the number of bytes that are required to store each of the C# data types. For an int, you need 4 bytes of storage. For a short you need 2. The amount of memory used determines how big or small a number can be that is stored. You'll learn more about this in the following sections.

The sizeof keyword is not one that you will use very often; however, it is useful for illustrating the points in today's lesson. The sizeof keyword taps into memory to determine the size of the variable or data type. With C#, you avoid tapping directly into memory. In line 8, an extra keyword is added—unsafe. If you don't include the unsafe keyword, you get an error when you compile this program. For now, understand that the reason unsafe is added is because the sizeof keyword works directly with memory.

Caution: The C# keyword sizeof can be used; however, you should generally avoid it. The sizeof keyword sometimes accesses memory directly to find out the size. Accessing memory directly is something to be avoided in pure C# programs.

Storing Information with Variables in C#

Integral Data Types

Until this point, you have been using one of the integral data types—int. Integral data types store integers. Recall that an integer is basically any numeric value that does not include a decimal or a fractional value. The numbers 1, 1,000, 56 trillion, and - 534 are integral values.

C# provides nine integral data types, including the following:

Integers (int and uint)

Shorts (short and ushort)

Longs (long and ulong)

Bytes (byte and sbyte)

Characters (char)

Integers

As you saw in Listing 3.4, an integer is stored in 4 bytes of memory. This includes both the int and uint data types. The int data type has been used in many of the programs you have seen so far. Although you might not have known it, this data type cannot store just any number. Rather, it can store any signed whole number that can be represented in 4 bytes or 32 bits - any number between - 2,147,483,648 and 2,147,483,647.

A variable of type int is signed, which means it can be positive or negative. Technically, 4 bytes can hold a number as big as 4,294,967,295; however, when you take away one of the 32 bits to keep track of positive or negative, you can go only to 2,147,483,647. You can, however, also go to - 2,147,483,648.

Note: As you learned earlier, information is stored in units called bytes. A byte is actually composed of 8 bits. A bit is the most basic unit of storage in a computer. A bit can have one of two values - 0 or 1. Using bits and the binary math system, you can store numbers in multiple bits. In Appendix C, "Working with Number Systems," you can learn the details of binary math.

If you want to use a type int to go higher, you can make it unsigned. An unsigned number can only be positive. The benefit should be obvious. The uint data type declares an unsigned integer. The net result is that a uint can store a value from 0 to 4,294,967,295.

What happens if you try to store a number that is too big? What about storing a number with a decimal point into an int or uint? What happens if you try to store a negative number into an uint? Listing 3.5 answers all three questions.

Analysis

This program will not compile. As you can see, the compiler catches all three problems that were questioned. In line 14 you try to put a number with a decimal point into an integer. In line 15 you try to put a number that is too big into an integer. Remember, the highest number that can go into an int is 2,147,483,647. Finally, in line 16, you try to put a negative number into an unsigned integer (uint). As the output shows, the compiler catches each of these errors and prevents the program from being created.

Shorts

The int and uint data types used 4 bytes of memory for each variable declared. There are a number of times when you don't need to store numbers that are that big. For example, you don't need big numbers to keep track of the day of the week (numbers 1 to 7), to store a person's age, or to track the temperature to bake a cake.

When you want to store a whole number and you want to save some memory, you can use short and ushort. A short, like an int, stores a whole number. Unlike an int, it is only 2 bytes instead of 4. If you look at the output from Listing 3.4, you see that sizeof returned 2 bytes for both short and ushort. If you are storing both positive and negative numbers, you'll want to use short. If you are storing only positive and you want to use the extra room, you'll want to use ushort. The values that can be stored in a short are from - 32,768 to 32,767. If you use a ushort, you can store whole numbers from 0 to 65535.

Longs

If int and uint are not big enough for what you want to store, there is another data type to use—long. As with short and int, there is also an unsigned version of the long data type called ulong. Looking at the output from Listing 3.4, you can see that long and ulong each use 8 bytes of memory. This gives them the capability of storing very large numbers. A long can store numbers from - 9,223,372,036,854,775,808 to 9,223,372,036,854,775,807. An ulong can store a number from 0 to 18,446,744,073,709,551,615.

Bytes

As you have seen, you can store whole numbers in data types that take 2, 4, or 8 bytes of memory. For those times when your needs are very small, you can store a whole number in a single byte. To keep things simple, the data type that uses a single byte of memory for storage is called a byte! As with the previous integers, there is both a signed version, sbyte, and an unsigned version, byte. A sbyte can store a number from - 128 to 127. An unsigned byte can store a number from 0 to 255.

Characters

In addition to numbers, you will often want to store characters. Characters are letters, such as A, B, or C, or even extended characters such as the smiley face. Additional characters that you might want to store are characters such as $, %, or *. You might even want to store foreign characters.

A computer does not recognize characters. It can recognize only numbers. To get around this, all characters are stored as numeric values. To make sure that everyone uses the same values, a standard was created called Unicode. Within Unicode, each character and symbol is represented by a single whole number. This is why the character data type is considered an integral type.

To know that numbers should be used as characters, you use the data type char. A char is a number stored in 2 bytes of memory that is interpreted as a character. Listing 3.6 presents a program that uses char values.

Output

Number Value
60 is <
61 is =
62 is >
63 is ?
64 is @
65 is A
66 is B
67 is C
68 is D
69 is E
70 is F
71 is G
72 is H
73 is I
74 is J
75 is K
76 is L
77 is M
78 is N
79 is O
80 is P
81 is Q
82 is R
83 is S
84 is T
85 is U
86 is V
87 is W
88 is X
89 is Y
90 is Z
91 is [
92 is \
93 is ]
94 is ^
95 is _

Analysis

This listing displays a range of numeric values and their character equivalents. In line 11 an integer is declared called ctr. This variable is used to cycle through a number of integers. Line 12 declares a character variable called ch. Line 14 prints headings for the information that will be displayed.

Line 16 contains something new. For now, don't worry about fully understanding this line of code. On Day 5, "Control Statements," you learn all the glorious details. For now know that this line sets the value of ctr to 60. It then runs lines 18 and 19 before adding 1 to the value of ctr. It keeps doing this until ctr is no longer less than or equal to 95. The end result is that lines 18 and 19 are run using the ctr with the value of 60, then 61, then 62, and on and on until ctr is 95.

Line 18 sets the value of ctr (first 60) and places it into the character variable, ch. Because ctr is an integer, you have to tell the computer to convert the integer to a character, which the (char) statement does. You'll learn more about this later.

Line 19 prints the values stored in ctr and ch. As you can see, the integer ctr prints as a number. The value of ch, however, does not print as a number; it prints as a character. As you can see from the output of this listing, the character A is represented by the value 65. The value of 66 is the same as the character B.

Note: A computer actually recognizes only 1s and 0s (within bits). It recognizes these as on or off values (or positive charges versus negative charges). A binary number system is one that uses 1s and 0s to represent its numbers. Appendix C explains the binary number system.

Storing Information with Variables in C#

Character Literals

How can you assign a character to a char variable? You place the character between single quotes. For example, to assign the letter a to the variable my_char, you use the following:

my_char = 'a';

In addition to assigning regular characters, there are also several extended characters you will most likely want to use. You have actually been using one extended character in a number of your listings. The \n that you've been using in your listings is an extended character. This prints a newline character. Table 3.2 contains some of the most common characters you might want to use. Listing 3.7 shows some of these special characters in action.

Table 3.2: Extended Characters.

Characters

Meaning

\b

Backspace

\n

Newline

\t

Horizontal tab

\\

Backslash

\'

Single quote

\"

Double quote

Note: The extended characters in Table 3.2 are often called escape characters because the slash "escapes" from the regular text and indicates that the following character is special (or extended).

Output

This is the first line of text
Skipped three lines
one two three <-tabbed
A quote: '
double quote: "
ch1 = Z cH3 = x

Analysis

This listing illustrates two concepts. First, in line 10 and 11 you see how a character can be assigned to a variable of type char. It is as simple as including the character in single quotes. In lines 13 to 17, you see how to use the extended characters. There is nothing special about line 13. Line 14 prints three newlines followed by some text. Line 15 prints one, two, and three, separated by tabs. Line 16 displays a single quote and a double quote. Notice that there are two double quotes in a row at the end of this line. Finally, line 17 prints the values of ch1 and cH3.

Floating Point

Not all numbers are whole numbers. For those times when you need to use numbers that might have decimals, you need to use different data types. As with storing whole numbers, there are different data types you can use, depending on the size of the numbers you are using and the amount of memory you want to use. The two primary types are float and double.

float

A float is a data type for storing numbers with decimal places. For example, in calculating the circumference or area of a circle, you often end up with a result that is not a whole number. Any time you need to store a number such as 1.23 or 3.1459, you need a nonintegral data type.

The float data type stores numbers in 4 bytes of memory. As such, it can store a number from approximately 1.5*10-45 to 3.4*1038.

Note: 1038 is equivalent to 10*10, 37 times. The result is 1 followed by 38 zeros, or 100,000,000,000,000,000,000,000,000,000,000,000,000. 10-45 is 10/10, 44 times. The result is 44 zeros between a decimal point and a 1, or .000000000000000000000000000000000000000000001.

Warning: A float can retain only about 7 digits of precision, which means it is not uncommon for a float to be off by a fraction. For example, subtracting 9.90 from 10.00 might result in a number different from .10. It might result in a number closer to .099999999. Generally such rounding errors are not noticeable.

double

Variables of type double are stored in 8 bytes of memory. This means they can be much bigger than a float. A double can generally be from 5.0*10-324 to 1.7*10308. The precision of a double is generally from 15 to 16 digits.

Note: C# supports the 4-byte precision (32 bits) and 8-byte precision (64 bits) of the IEEE 754 format, so certain mathematical functions return specific values. If you divide a number by 0, the result is infinity (either positive or negative). If you divide 0 by 0, you get a Not-a-Number value. Finally, 0 can be both positive and negative. For more on this, check your C# documentation.

Decimal

C# provides another data type that can be used to store special decimal numbers. This is the decimal data type. This data type was created for storing numbers with greater precision. When you store numbers in a float or double, you can get rounding errors. For example, storing the result of subtracting 9.90 from 10.00 in a double could result in the string 0.099999999999999645 instead of 0.10. If this math is done with decimal values, the 0.10 is stored.

Tip: If you are calculating monetary values or doing financial calculations where precision is important, you should use a decimal instead of a float or a double.

A decimal number uses 16 bytes to store numbers. Unlike the other data types, there is not an unsigned version of decimal. A decimal variable can store a number from 1.0*10-28 to approximately 7.9*1028. It can do this while maintaining precision to 28 places.

Boolean

The last of the simple data types is the Boolean. Sometimes you need to know whether something is on or off, true or false, yes or no. Boolean numbers are generally set to one of two values: 0 or 1.

C# has a Boolean data type called a bool. As you can see in Listing 3.4, a bool is stored in 1 byte of memory. The value of a bool is either true or false, which are C# keywords. This means you can actually store true and false in a data type of bool.

"Yes," "no," "on," and "off" are not keywords in C#. This means you cannot set a Boolean variable to these values. Instead, you must use true or false.

Checking Versus Unchecking

Earlier in today's lesson you learned that if you put a number that is too big into a variable, an error is produced. There are times when you might not want an error produced. In those cases, you can have the compiler avoid checking the code. This is done with the unchecked keyword. Listing 3.8 illustrates this.

Output

val1 is 2147483647
val2 is -2147483648

Analysis

This listing uses unchecked in line 13. The brackets on line 14 and 16 enclose the area to be unchecked. When you compile this listing, you do not get any errors. When you run the listing, you get what might seem like a weird result. The number 2,147,483,647 is the largest number that a signed int variable can hold. As you see in line 10, this maximum value has been assigned to var1. In line 15, the unchecked line, 1 is added to what is already the largest value var1 can hold. Because this line is unchecked, the program continues to operate. The result is that the value stored in var1 rolls to the most negative number.

This operation is similar to the way an odometer works in a car. When the mileage gets to the maximum, such as 999,999, adding 1 more mile (or kilometer) sets the odometer to 000,000. It isn't a new car with no miles, it is simply a car that no longer has a valid value on its odometer. Rather than rolling to 0, a variable is going to roll to the lowest value it can store. In this listing, that value is -2,147,483,648.

Change line 13 to the following and recompile and run the listing:

13: checked

The program compiled, but will it run? Executing the program causes an error. If you are asked to run your debugger, you'll want to say no. The error you get will be similar to the following:

Exception occurred: System.OverflowException: An exception
of type System.OverflowException was thrown.
at sizes.Main()

On later days, you'll see how to deal with this error in your program. For now, you should keep in mind that if you believe there is a chance to put an invalid value into a variable, you should force checking to occur.

Storing Information with Variables in C#

Data Types Simpler than .NET

The C# data types covered so far are considered simple data types. The simple data types are sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, bool, and decimal. On Day 1 and Day 2, "Understanding C# Programs," you learned that C# programs execute on the Common Language Runtime (CLR). Each of these data types corresponds directly to a data type that the CLR uses. Each of these types is considered simple because there is a direct relationship to the types available in the CLR and thus in the .NET Framework. Table 3.3 presents the .NET equivalent of the C# data types.

Table 3.3:—C# and .NET Data Types

C# Data Type

.NET Data Type

sbyte

System.SByte

byte

System.Byte

short

System.Int16

ushort

System.UInt16

int

System.Int32

uint

System.UInt32

long

System.Int64

ulong

System.UInt64

char

System.Char

float

System.Single

double

System.Double

bool

System.Boolean

decimal

System.Decimal

If you want to declare an integer using the .NET equivalent declaration—even though there is no good reason to do so—you use the following:

System.Int32 my_variable = 5;

As you can see, System.Int32 is much more complicated than simply using int. Listing 3.9 shows the use of the .NET data types.

Output

Analysis

Lines 12 and 13 declare an int and a double. Lines 15 and 16 print these values. This listing operates like those you've seen earlier, except it uses the .NET data types.

In your C# programs, you should use the simple data types rather than the .NET types. All the functionality that the .NET types have is available to you in the simpler commands that C# provides. You should, however, understand that the simple C# data types translate to .NET equivalents. You'll find that all other programming languages that work with the Microsoft .NET types also have data types that translate to these .NET types.

Note: The Common Type System (CTS) is a set of rules that data types within the CLR must adhere to. The simple data types within C# adhere to these rules, as do the .NET data types. If a language follows the CTS in creating its data types, the data created and stored should be compatible with other programming languages that also follow the CTS.

Literals Versus Variables

In the examples you've looked at so far, you have seen a lot of numbers and values used that were not variables. Often, you will want to type a number or value into your source code. A literal value stands on its own within the source code. For example, in the following lines of code, the number 10 and the value "Bob is a fish" are literal values. As you can see, literal values can be put into variables.

int x = 10;
myStringValue = "Bob is a fish";

Numeric Literals

In many of the examples, you have used numeric literals. By default, a numeric literal is either an int or a double. It is an int if it is a whole number, and it is a double if it is a floating-point number. For example, consider the following:

nbr = 100;

In this example, 100 is a numeric literal. By default, it is considered to be of type int, regardless of what data type the nbr variable is. Now consider the following:

nbr = 99.9;

In this example, 99.9 is also a numeric literal; however, it is of type double by default. Again, this is regardless of the data type that nbr is. This is true even though 99.9 could be stored in a type float. In the following line of code, is 100. an int or a double?

x = 100.;

This is a tough one. If you guessed int, you are wrong. Because there is a decimal included with the 100, it is a double.

Integer Literal Defaults

When you use an integer value, it is put into an int, uint, long, or ulong depending on its size. If it will fit in an int or uint, it will be. If not, it will be put into a long or ulong. If you want to specify the data type of the literal, you can use a suffix on the literal. For example, to use the number 10 as a literal long value(signed or unsigned), you write it like the following:

10L;

You can make an unsigned value by using a u or a U. If you want an unsigned literal long value, you can combine the two suffixes: ul.

Note: The Microsoft C# compiler gives you a warning if you use a lowercase l to declare a long value literal. The compiler provides this warning to help you be aware that it is easy to mistake a lowercase l with the number 1.

Floating-Point Literal Defaults

As stated earlier, by default, a decimal value literal is a double. To declare a literal that is of type float, you include an f or F after the number. For example, to assign the number 4.4 to a float variable, my_float, you use the following:

my_float = 4.4f;

To declare a literal of type decimal, you use a suffix of m or M. For example, the following line declares my_decimal to be equal to the decimal number 1.32.

my_decimal = 1.32m;

Boolean Literals (true and false)

Boolean literals have already been covered. The values true and false are literal. They also happen to be keywords.

String Literals

When you put characters together, they make words, phrases, and sentences. In programming parlance, a group of characters is called a string. A string can be identified because it is contained between a set of double quotes. You have actually been using strings in the examples so far. For example, the Console.WriteLine routine uses a string. A string literal is any set of characters between double quotes. The following are examples of strings:

"Hello, World!"
"My Name is Bradley"
"1234567890"

Because these numbers are between quotation marks, the last example is treated as a string literal rather than as a numeric literal.

Note: You can use any of the special characters from Table 3.3 inside a string.

Constants

In addition to using literals, there are times when you want to put a value in a variable and freeze it. For example, if you declare a variable called PI and you set it to 3.1459, you want it to stay 3.1459. There is no reason to change it. Additionally, you want to prevent people from changing it.

To declare a variable to hold a constant value, you use the const keyword. For example, to declare PI as stated, you use the following:

const float PI = 3.1459;

You can use PI in a program; however, you will never be able to change its value. The const keyword freezes its contents. You can use the const keyword on any variable of any data type.

Tip: To help make it easy to identify constants, you can enter their names in all capital letters. This makes it easy to identify the fact that the variable is a constant.

Storing Information with Variables in C#

Reference Types

To this point, you have seen a number of different data types. C# offers two primary ways of storing information: by value (byval) and by reference (byref). The basic data types that you have learned about store information by value.

When a variable stores information by value, the variable contains the actual information. For example, when you store 123 in an integer variable called x, the value of x is 123. The variable x actually contains the value 123.

Storing information by reference is a little more complicated. If a variable stores by reference, rather than storing the information in itself, it stores the location of the information. In other words, it stores a reference to the information. For example, if x is a "by reference" variable, it contains information on where the value 123 is located. It does not store the value 123. Figure 3.1 illustrates the difference.

Figure 3.1:By reference versus by value.

The data types used by C# that store by reference are

Classes

Strings

Interfaces

Arrays

Delegates

Each of these data types is covered in detail throughout the rest of this book.

Summary

In today's lesson, you learned how the computer stores information. You focused on the data types that store data by value, including int, uint, long,ulong, bool, char, short, ushort, float, double, decimal, byte, and ubyte. In addition to learning about the data types, you learned how to name and create variables. You also learned the basics of setting values in these variables, including the use of literals. Table 3.4 lists the data types and information about them.

Table 3.4: C# Data Types

C# Data Type

.NET Data Type

Size in Bytes

Low Value

High Value

sbyte

System.SByte

1

-128

127

byte

System.Byte

1

0

255

short

System.Int16

2

-32,768

32,767

ushort

System.UInt16

2

0

65,535

int

System.Int32

4

-2,147,483,648

2,147,483,647

uint

System.UInt32

4

0

4,294,967,295

long

System.Int64

8

- 9,223,372,036, 854,775,808

9,223,372,036, 854,775,807

ulong

System.UInt64

8

0

18,446,744,073 709,551,615

char

System.Char

2

0

65,535

float

System.Single

4

1.5 x 10-45

3.4 x 1038

double

System.Double

8

5.0 x 10-324

1.7 x 1010308

bool

System.Boolean

1

false (0)

true (1)

decimal

System.Decimal

16

1.0 x 10-28

approx. 7.9 x 1028

Q&A

Why shouldn't all numbers be declared as the larger data types instead of the smaller data types?

Although it might seem logical to use the larger data types, this would not be efficient. You should not use any more system resources (memory) than you need.

What happens if you assign a negative number to an unsigned variable?

You get an error by the compiler saying you can't assign a negative number to an unsigned variable if you do this with a literal. If you do a calculation that causes an unsigned variable to go below 0, you get erroneous data. On later days, you will learn how to check for these erroneous values.

A decimal value is more precise than a float or a double value. What happens with rounding when you convert from these different data types?

When converting from a float, double, or decimal to one of the whole number variable types, the value is rounded. If a number is too big to fit into the variable, an error occurs.

When a double is converted to a float that is too big or too small, the value is represented as infinity or 0, respectively.

When a value is converted from a float or double to a decimal, the value is rounded. This rounding occurs after 28 decimal places and occurs only if necessary. If the value being converted is too small to be represented as a decimal, the new value is set to 0. If the value is too large to store in the decimal, an error occurs.

For conversions from decimal to float or double, the value is rounded to the nearest value the float or double can hold. Remember, a decimal has better precision than a float or a double. This precision is lost in the conversion.

What other languages adhere to the Common Type System (CTS) in the Common Language Runtime (CLR)?

Microsoft Visual Basic.Net (version 7) and Microsoft Visual C++.NET (version 7) both support the CTS. Additionally there are versions of a number of other languages that are ported to the CTS. These include Python, COBOL, Perl, Java, and more. Check out the Microsoft Web site for additional languages.

Workshop

The Workshop provides quiz questions to help you solidify your understanding of the material covered and exercises to provide you with experience in using what you've learned. Try to understand the quiz and exercise answers before continuing to the next day's lesson. Answers are provided in Appendix A, "Answers."

Quiz

What are the by value data types available in C#?

What is the difference between a signed and unsigned variable?

What is the smallest data type you can use to store the number 55?

What is the biggest number that a type short variable can hold?

What numeric value is the character B?

How many bits in a byte?

What literal values can be assigned to a Boolean variable?

Name three of the reference data types.

Which floating-point data type has the best precision?

What .NET data type is equivalent to the C# int data type?

Exercises

Change the range of values in Listing 3.6 to print the lowercase letters.

Write the line of code that declares a variable named xyz of type float and assign the value of 123.456 to it.

Which of the following variable names are valid?

X

PI

12months

sizeof

nine

BUG BUSTER: The following program has a problem. Enter it in your editor and compile it. Which lines generate error messages?