Скачиваний:
64
Добавлен:
15.03.2015
Размер:
4.31 Mб
Скачать

C H A P T E R 4

A GUIDED TOUR THROUGH C#:

PART II

You will learn about the following in this chapter:

More fundamental C# elements

How to write and call your own

 

building on those presented in

 

user-defined methods

 

Chapter 3, “A Guided Tour

Multiline comments and their

 

Through C#: Part I,” through a

 

 

different styles

 

source code driven presentation

 

 

 

 

The namespace concept and an

How C# evaluates simple

 

expressions

 

understanding for how this fea-

 

 

 

 

 

ture can help organize and access

How methods can be used to

 

C# components

 

simplify your source code

The int type for storing whole

 

 

 

numbers

 

 

Introduction

A new source code example containing a simple calculator is presented in this chapter, along with several new elements of the C# language.

Essential Elements of SimpleCalculator.cs

You have already met the string type in Chapter 3, “A Guided Tour through C#: Part I.” The calculator program you will see shortly introduces another type called int, which is a commonly used type for variables holding whole numbers. You will further see how you can define and use your own methods. The important namespace concept, enabling classes and other types to be organized into a single coherent hierarchical structure while providing easy access, is also presented. WriteLine will show off by revealing its versatility, and you will finally meet the handy Math class and apply a couple of methods from this part of the .NET Framework class library.

92 C# PRIMER PLUS

Presenting SimpleCalculator.cs

The source code in Listing 4.1 calculates the sum, product, minimum, and maximum value of two numbers entered by the user. The program prints the answers on the command console.

LISTING 4.1 Source Code for SimpleCalculator.cs

01: using System; 02:

03: /*

04:* This class finds the sum, product,

05:* min and max of two numbers

06:*/

07: public class SimpleCalculator 08: {

09:public static void Main()

10:{

11:int x;

12:int y;

13:

14:Console.Write(“Enter first number: “);

15:x = Convert.ToInt32(Console.ReadLine());

16:Console.Write(“Enter second number: “);

17:y = Convert.ToInt32(Console.ReadLine());

18:Console.WriteLine(“The sum is: “ + Sum(x, y));

19:Console.WriteLine(“The product is: “ + Product(x, y));

20:Console.WriteLine(“The maximum number is: “ + Math.Max(x, y));

21:Console.WriteLine(“The minimum number is: “ + Math.Min(x, y));

22:}

23:

24:// Sum calculates the sum of two int’s

25:public static int Sum(int a, int b)

26:{

27:int sumTotal;

28:

29:sumTotal = a + b;

30:return sumTotal;

31:}

32:

33:// Product calculates the product of two int’s

34:public static int Product(int a, int b)

35:{

36:int productTotal;

37:

38:productTotal = a * b;

39:return productTotal;

40:}

41:}

The following is the sample output when the user enters 3 and 8:

Enter first number: 3<enter>

Enter second number: 8<enter>

Chapter 4 • A GUIDED TOUR THROUGH C#: PART II 93

The sum is:

11

The product

is: 24

The maximum

number is: 8

The minimum

number is: 3

A quick reference to the source code in Listing 4.1 is provided in Listing 4.2. You will most likely recognize several constructs from Shakespeare.cs in Chapter 2, “Your First C# Program,” and Hello.cs in Chapter 3, and you will probably begin to form a picture of what the fundamental elements of a typical C# program look like.

LISTING 4.2 Brief Analysis of Listing 4.1

01:Allow this program to use shortcuts

when accessing classes in System namespace

02: Empty line

03: Begin multi-line comment

04:Second line of multi-line comment: This class finds the sum, product,

05: Third line of multi-line comment: min and max of two numbers 06: End multi-line comment

07: Begin the definition of a class named SimpleCalculator 08: Begin the block of the SimpleCalculator class definition

09:Begin the definition of a method called Main()

10:Begin the block of the Main() method definition

11:Declare a variable called x whichcan store whole numbers (integers).

12:Declare a variable called y whichcan store whole numbers (integers).

13:Empty line

14:Print out: Enter first number:

15:Store users answer in the x variable. Move down one line

16:Print out: Enter second number:

17:Store users answer in the y variable. Move down one line

18:Print out: The sum is: followed by thevalue returned from the Sum method.

19:Print out: The product is: followed by thevalue returned from the Product method.

20:Print out: The maximum number is: followed by thevalue returned by the Max method of the Math class.

21:Print out: The minimum number is: followed by thevalue returned by the Min method of the Math class

22:End the block containing the Main() method definition

23:Empty line

24:Make comment: Sum calculates the sum of two int’s

25:Begin the definition of a the method Sum(int a, int b)

26:Begin the block of the Sum(int a, int b) method definition

27:Declare a local variable called sumTotal whichcan store whole integers.

28:Empty line

29:Find the sum of a and b; store this result in sumTotal

30:Terminate the method; return the value of sumTotal to the caller.

31:End the block of the Sum(int a, int b) method

32:Empty line.

94 C# PRIMER PLUS

LISTING 4.2 continued

33:Make comment: Product calculates the product of two int’s

34:Begin the definition of a the method Product(int a, int b)

35:Begin the block of the Product(int a, int b) method definition

36:Declare a local variable called productTotal whichcan store whole integers

37:Empty line

38:Find the product of a and b; store this result in productTotal.

39:Terminate the method; return thevalue of productTotal to the caller

40:End the block of the Product(int a, int b) method

41:End block containing SimpleCalculator class definition

By now, I assume you are comfortable writing source code in Notepad and compiling it with the csc command of the command console; therefore, I will let you write and run the source code in Listing 4.1 in peace now.

A Closer Look at SimpleCalculator.cs

SimpleCalculator.cs is probably not a program people would rush to buy in their local software store, but it certainly contains a few essential ingredients that would be part of most C# best-selling computer programs. The following section will take a closer look at Listing 4.1 to uncover them.

Introducing Namespaces

We need to introduce the namespace concept to get an initial understanding for line 1. To this end, we move to a seemingly unrelated place—your home.

01: using System;

Have you ever, like me, had the feeling of an invisible spirit at play that constantly turns your home into a place resembling a test site for new explosives, despite your best efforts to the contrary?

There seems to be a large number of different objects in a home causing the mess to relentlessly get out of hand—shirts, spoons, knives, shampoo, books, CDs, apples, pots, and Picasso paintings all pile up.

How, then, do we manage to make our home neat and tidy before the family arrives at Christmas? Containers are the solution to our problem. We form small hierarchies of containers inside other containers holding similar kinds of objects. For example, a kitchen knife (the object) would be positioned in the kitchen (here regarded as being a container) in the upperleft drawer container, in the cutlery tray container, in the knife compartment container, together with other more-or-less similar knives.

Not only do these containers help us to make our home nice and tidy, they also allow us to get an overview of where different objects are stored in the house. We are even able to show our guests where to find different objects. When everything is tidy around Christmas time, we can confidently tell our new friend Fred how to find a knife. If we turned our home into a small hotel with new visitors arriving on a daily basis, we might further create a little system for how

Chapter 4 • A GUIDED TOUR THROUGH C#: PART II 95

to tell new guests where to find different objects. In this referencing system, we could decide to simply put a dot (period) between each container name. A guest looking for a knife then might only need the message Kitchen.UpperLeftDrawer.CutleryTray.KnifeCompartment.

As a final bonus, we avoid name collision problems. For example, we can differentiate between a knife used for fishing found in the garage and a knife used for eating found in the kitchen, even though they are both referred to as knife. This is simply done by specifying where each particular knife is positioned. Accordingly, the kitchen knife specified by

Kitchen.UpperLeftDrawer.CutleryTray.KnifeCompartment.Knife would likely be different from our fishing knife referenced by

Garage.FishingCupboard.UpperRightDrawer.KnifeBox.Knife.

The kitchen contains not only drawers and boxes, it also can contain objects like chairs and tables. Similarly, every container can contain not only other containers but also objects.

The practical container system described here is similar in concept to the namespace idea. The namespaces act as containers for the many classes we construct and must keep track of. Namespaces help us organize our source code when developing our programs (keeping our “home” of classes “nice and tidy,” allowing us to know where each class is kept). They also allow us to tell our “guest” users where classes are kept, so they (other programmers) easily can access and reuse our classes. Name collisions between classes created by different programmers, perhaps from different software companies, are eliminated, because each class can be uniquely referenced through its namespace name.

Recall the .NET Framework documentation viewed previously. If you had a good look, you would have encountered a myriad of classes. In fact, the .NET Framework contains several thousand classes. Consequently, the .NET Framework is heavily dependent on namespaces to keep its classes organized and accessible.

The .NET Framework contains an important namespace called System. It holds specific classes fundamental to any C# program. Many other System classes are frequently used by most C# programs. It also includes our familiar Console class used extensively in Listing 3.1 (lines 9–11 and 13–15) of Chapter 3 and lines 14–21 in Listing 4.1.

Tip

Avoid giving names to classes that are identical to important, often-used namespace identifiers, such as System, Collections, Forms, and IO.

Listings 3.1 and 4.1 represent two different options available when accessing classes of the System (or any other) namespace in your source code:

Without using System; in the source code, as in line 1 of Listing 3.1—We must then reference the System namespace explicitly every time we use one of its classes, as in Listing 3.1, line 14:

96 C# PRIMER PLUS

method identifier p

public static void Ma

{

method

 

definition

statements

 

{

With using System;, as in line 1 of Listing 4.1—We can use any class of the System namespace without the repetitive tedious chore of explicitly typing System. The previous example of code could then be truncated to the following (just like lines 14–21 of Listing 4.1).

Console.WriteLine("Bye Bye!");

System namespace reference (removed and not required)

using essentially frees us from the burden of writing fully-qualified namespace names in numerous places of our source code. It also enhances the readability of our code by abbreviating otherwise lengthy references.

Note

using can only be applied to namespaces and not classes, so the following line is invalid:

using System.Console; invalid

class

Multi-Line Comments

You have already met the double slash // used for single line comments in lines 1 and 4 of Listing 3.1. /* (forward slash star) indicates the beginning of a multi-line comment. Anything written between /* and the matching */ is a comment and is ignored by the compiler (as in line 3 of Listing 4.1).

03: /*

Chapter 4 • A GUIDED TOUR THROUGH C#: PART II 97

// could be used for multi-line comments, but you would have to include // in every line of the comment, as shown in the following:

//This comment spans //over two lines

/* */ could likewise be used for a single line comment:

/* This is a single line comment */

Most programmers seem to prefer // for one or at most only a few lines of comments, whereas /* */ facilitates elaborate comments spanning numerous lines.

A few different multi-line commenting styles are often seen. The start comment /* and end comment */ have been highlighted so it is easier for you to locate the beginning and end of each comment.

/* Many attempts to communicate

are nullified by saying too much.

Robert Greenleaf

*/

/*

*I have made this rather

*long letter because I haven’t

*had the time to make it shorter.

*Blaise Pascal

*/

/**********************************************

*It’s a damn good program.

*If you have any comments,

*write them on the back

*of the cheque.

*

* Adapted from Erle Stanley Gardner

*********************************************/

Probably not the typical content of a comment, but these comments illustrate three different popular multi-line commenting styles and possess wisdom applicable when commenting source code.

The actual text of the multi-line comment is seen in lines 4 and 5 of Listing 4.1:

04:* This class finds the sum, product,

05:* min and max of two numbers

In line 6, */ matches /* of line 3 and terminates the multi-line comment.

06:*/

Inferior choice of identifiers

98 C# PRIMER PLUS

Tip

Making good comments is like adding salt to your food; you have to add the right amount. Excessive use of comments obscures the readability of the code and gives the reader more to read than necessary. It is as damaging as too few comments.

Rather than merely restating what the code does by using different words, try to describe the overall intent of the code.

Poor comment. It only repeats in a

Coding nightmare: verbose fashion what is expressed very precisely in C# in the next line.

/*

*The next line adds s1 to s2. s3 is then

*again added to the previous result and finally s4 is

*added to the latter result. This result is then stored in

*the ss variable. s1, s2, s3 and s4 all represent different

*speeds of a car. ss is the sum of those speeds.

*/

ss = s1 + s2 + s3 + s4;

/*

*The next line takes the ss variable from above and divides

*it by 4 it then stores this result in the variable a which

* then is the average of s1, s2, s3 and s4.

 

*/

 

 

Another poor comment.

a = ss / 4;

 

 

Bad identifier choice.

 

 

 

 

 

 

 

 

 

Let’s see how we can improve this source code:

Improved code

the comment states the intent of the code briefly

//Calculate the average speed of a car

speedSum = speed1 + speed2 + speed3 + speed4;

averageSpeed = speedSum / 4;

Good choice of identifiers

makes the code self documenting

Chapter 4 • A GUIDED TOUR THROUGH C#: PART II 99

Declaring a Variable of Type int

Line 11 contains a statement declaring a variable called x. Remember how we previously declared a variable of type string in Listing 3.1 line 7, enabling it to contain a string of characters (text). This time, we have exchanged the keyword string with the keyword int. It dictates the type of x to be a specific kind of integer taking up 32 bits of memory (4 bytes).

11:int x;

Integers, in general are whole numbers, such as 8, 456, and –3123. This contrasts with float- ing-point numbers that include a fraction. 76.98, 3.876, and –10.1 are all examples of floating point numbers. Because x now takes up 32 bits of memory, it can represent numbers in the

–2147483648–2147483647 range. We will not examine this fact closely now, but observe the following calculation:

232 /2 = 2147483648

The first 2 is the bit size, the 32 is the number of bits, and the /2 shows that half of the available numbers are allocated for positive numbers, and half for negative numbers.

Binary numbers are discussed at length in Appendix D, “Number Systems,” which is found on www.samspublishing.com, while integers and their range will be discussed thoroughly in Chapter 6, “Types Part I: The Simple Types.”

Line 12 declares a variable called y to be of type int.

12:int y;

x and y are usually considered to be unacceptable names for variables because identifiers must be meaningful and reflect the content of the variable. In this particular case, however, x and y are involved in generic arithmetic calculations and do not represent any particular values, such as average rainfall or the number of newborns in Paris. Any math whiz kid would immediately accept x and y as valid name choices in a mathematical equation with equivalent generic characteristics.

Converting from Type string to Type int

Any user response typed on the console, followed by Enter, and received by Console.ReadLine() is considered to be of type string by the C# program. Even a number like 432 is initially presumed to merely be a set of characters and could easily be ABC or #@$ instead.

A number represented as a string cannot be stored directly in a variable of type int; so we must first convert the string variable to a variable of type int before commencing.

By using the ToInt32 method of the Convert class as in line 15, the program attempts to convert any user input to an int number. After successful conversion, the part on the right side of the equals sign in line 15 will represent the corresponding int number, and be stored in x.

However, the conversion can only take place if the user input matches an int number. Thus, inputs such as 57.53 or three hundred will trigger an error, whereas 109 or 64732 are accepted.

15: x = Convert.ToInt32(Console.ReadLine());

100 C# PRIMER PLUS

Creating and Invoking Your Own Methods

Before line 18 can be understood properly, we need to jump ahead and look at lines 25–31.

25:public static int Sum(int a, int b)

26:{

27:int sumTotal;

28:

29:sumTotal = a + b;

30:return sumTotal;

31:}

Until now, we have happily used pre-fabricated methods, such as Console.ReadLine() and Console.WriteLine(). Despite the vast array of functionality found in the .NET Framework and other available commercial class libraries, you will, when creating new unique source code, need to supply specialized functionality by writing your own user-defined methods.

Lines 25–31 are an example of a user-defined method called Sum.

Briefly explained, Sum, when called, receives two numbers. It adds the two numbers together and returns the result to the caller.

The definition for the Sum() method, with its method header, braces {}, and method body, follows the same general structure as the definition for the Main method.

Tip

Generally, classes represent objects, whereas methods represent actions. Try to adhere to the following when you name classes and methods:

Use nouns (Car, Airplane, and so on) when naming classes.

Use verbs for method names (DriveForward, MoveLeft, TakeOff, and so on).

The method header of line 25 is, in many ways, similar to the method header of Main in line 9 (recall the access modifier public and its ability to let a method be included in the interface of the class to which it belongs).

We have also previously introduced static, in line 5 of Listing 3.1, and will abstain from any further description of this keyword right now.

However, void has been replaced by int, and we see what looks like two variable declarations separated by a comma residing inside a pair of parentheses (int a, int b) located after Sum. This deserves an explanation.

Line 25 can be regarded as the interface of the Sum method. This interface facilitates the communication between the method calling Sum (in this case Main) and the method body of Sum.

In everyday language, an interface can be described as a feature or circumstance that enables separate (and sometimes incompatible) elements to communicate effectively.

Figure 4.1 zooms in on the process involved when Sum(int a, int b) of line 25 is invoked from line 18 Sum(x, y) of the Main() method. The two arrows marked Zoom simply indicate which parts have graphically been blown up and zoomed in on.

Chapter 4 • A GUIDED TOUR THROUGH C#: PART II 101

FIGURE 4.1

Invoking a user-defined method.

Invoking method

 

Invoked method

09: public static void Main()

 

method header

10: {

 

 

 

invoking Sum

 

 

 

:

 

 

 

:

 

 

 

public static int Sum(int a, int b)

Sum(x, y)

25:

18: ......

:Zoom

:arguments

22: }

Sum ( x, y )

Zoom

3

1

2

int Sum ( int a, int b )

formal parameters

3

30: return sum Total;

aand b in Sum’s method header are called formal parameters. A formal parameter is used in the method body as a stand-in for a value that will be stored here when the method is called. In this case, the values of the arguments x and y of line 18 will be plugged into a and b indicated with arrows 1 and 2, just as though the two assignment statements a=x; and b=y; were executed.

aand b can now be used inside the method body (in this case line 29) just like any regular declared variable initially holding the values of x and y.

The int in line 25 replacing void not only tells us that Sum returns a value of some sort, but also that this value is of type int. This leads us to line 30, where we find the C# keyword return.

30:return sumTotal;

return belongs to a type of statement called a return statement. When a return statement is executed, the method is terminated. The flow of execution is returned to the caller and brings along the value residing in the expression after return (in this case the value of sumTotal. See the arrows with number three in Figure 4.1).

Accordingly, the type of sumTotal must be compatible with the return type specified in the method header (in this case int), as illustrated in Figure 4.2.

No Data Are Returned from a void Method

When the keyword void is positioned in front of the method name in the method header, it indicates that when the runtime has finished executing the statements of the method, it will not return any data to the caller. Consequently the void keyword has the opposite meaning from the keyword int when put in front of the method name in the method header. The latter indicates that the method will always return a value of type int.

102 C# PRIMER PLUS

FIGURE 4.2

Return type of method header must match type of return expression.

25:public static int Sum(int a, int b)

26:

{

compatible types required because…

27: int sumTotal;

28:

29:sumTotal = a + b;

30:return sumTotal; …sumTotal is returned to invoking method

31: }

return statement

Tip

When you program in C#, think in terms of building blocks. Classes, objects, and methods are meant for this approach. Break down your programs into manageable building blocks. In a C# program, you typically use classes and methods that are

From class libraries (NET Framework or other commercially available packages). Many class libraries can be obtained for free over the Internet.

Written by yourself and, as a result, contain user-defined classes and methods.

Created by other programmers, perhaps your fellow students or colleagues at work.

Don’t attempt to reinvent the wheel. Before throwing time and money into creating new classes and methods, check to see if equivalent functionality has already been implemented, tested by professional programmers, and made available in the form of highly efficient and robust software components.

An Assignment Statement

Line 29 is an assignment statement. a and b are added together using the + operator. The result is stored in the sumTotal variable due to the assignment operator = (see Figure 4.3). Let’s illustrate this by using the sample output example of from Listing 4.1, where the input provided was 3 and 8. When Sum is called, 3 and 8 are transferred to a and b, through x and y of Main. After the execution of line 29, sumTotal holds the value 11.

29:sumTotal = a + b;

Combining Strings and Method Calls

In line 18, we first need to focus on the Sum(x, y) part, which, as already shown, invokes the Sum method defined in lines 25–31 and sends the two arguments x and y along. Notice that we do not need to include ObjectName or ClassName as specified in the previously given conventions, ObjectName.MethodName(Optional_Arguments) and

ClassName.MethodName(Optional_Arguments), because the invoker and the invoked method reside inside the same class—SimpleCalculator.

FIGURE 4.3

Assigning the result of a calculation to a variable.

Chapter 4 • A GUIDED TOUR THROUGH C#: PART II 103

insert result of a+b in sumTotal

sumTotal = a + b

18:Console.WriteLine(“The sum is: “ + Sum(x, y));

After the Sum method returns, you can virtually substitute Sum(x, y) with sumTotal from line 30. In our example, Sum(x, y) will represent the value 11 (see Figure 4.4).

FIGURE 4.4

Sum(x, y) represents the value of sumTotal when Sum returns.

18:Console.WriteLine("The sum is: " + Sum(x, y));

25:public static int Sum(int a, int b)

26:{

27:int sumTotal;

28:

29:sumTotal = a + b;

30:return sumTotal;

31:}

Sum(x, y) represents the value of sumTotal

Even though Sum(x, y) resides inside another method call in the form of Console.WriteLine(), C# can easily cope and correctly resolves the sequence of events that need to take place. When the value of Sum(x, y) is needed, the call will be made. Line 18 could then, after lines 25–31 have been executed and the flow has returned to line 18, be thought of as:

Console.WriteLine(“The sum is: “ + 11);

Because 11 is inside the parentheses of a call to WriteLine, it is automatically converted to a string. Consequently, we can now look at line 18 as follows:

Console.WriteLine(“The sum is: “ + “11”);

We still have one odd detail to sort out—the + symbol between “The sum is: “ and “11”. When the + symbol is positioned between two numeric values, it adds them together in standard arithmetic fashion. However, when the C# compiler finds the + symbol surrounded by strings, it changes its functionality. It is then used to connect the two strings surrounding it, which results in “The sum is: 11”. In general, connecting or pasting together two strings to obtain a larger string is called concatenation, so the + symbol in this case is referred to as a concatenation operator.

Finally, line 18 has essentially been transformed to look like the following:

Console.WriteLine(“The sum is: 11”);

104 C# PRIMER PLUS

This is familiar to us and says, “Print out The sum is: 11 on the console.” Fortunately, this is exactly what we see when running the program.

The + Symbol: Adding or Concatenating?

The + operator can be used for different purposes. One moment it is used for a string concatenation; the next it is involved in adding numbers together. Due to this flexibility of the + operator, we say it is overloaded. Overloaded operators are very useful, but they come at a price; hard to trace bugs and mysterious results can sometimes appear.

For example, when + acting as a string concatenation operator is confused with + acting as an addition operator, the program produces unexpected results. Consider the following line of code:

Console.WriteLine(“x + 8 = “ + x + 8);

If x has the value 6, which output would you expect?

The actual output is x + 8 = 68, whereas many would have expected x + 8 = 14.

Why is that? Well first, “x + 8 = “ + x is concatenated to “x + 8 = 6” which again is concatenated with 8 to form x + 8 = 68.

A correct result printing x + 8 = 14 can be produced with the following code:

“x + 8 = “ + (x + 8)

KISS

The C# compiler is capable of resolving extremely complicated, nested, convoluted statements and programs. Programmers with a bit of experience sometimes attempt to show off by stretching this power to create some warped, weird, and intricate programs that nobody apart from themselves can understand. This kind of programming practice is acceptable if you want to have a bit of fun in your free time at home, but it has no place in properly constructed software.

Be humble! Follow the KISS principle—Keep It Simple Stupid.

Lines 34–40 are very similar to lines 25–31, the only differences being different method and variable names and, instead of calculating the sum, the Product method calculates the product of two numbers. Note that the asterisk (*) character is used to specify multiplication.

34:public static int Product(int a, int b)

35:{

36:int productTotal;

37:

38:productTotal = a * b;

39:return productTotal;

40:}

Lines 18 and line 19 are conceptually identical.

19: Console.WriteLine(“The product is: “ + Product(x, y));