It is a time-honored tradition to start a programming book with a “Hello World” program. In this chapter, we will create, compile, and run a simple “Hello World” program written in C#. The analysis of this brief program will introduce key features of the C# language.
Example 2-1 illustrates the fundamental elements of a very elementary C# program.
Example 2-1. A simple “Hello World” program in C#
class HelloWorld { static void Main( ) { // Use the system console object System.Console.WriteLine("Hello World"); } }
Compiling and running HelloWorld
displays the
words “Hello World” at the console. Let’s take a
closer look at this simple program.
The essence of object-oriented programming is the creation of new types. A type represents a thing. Sometimes the thing is abstract, such as a data table or a thread; sometimes it is more tangible, such as a button in a window. A type defines the thing’s general properties and behaviors.
If your program uses three instances of a button type in a window—say, an OK, a Cancel, and a Help button—each instance will share certain properties and behaviors. Each, for example, will have a size (though it might differ from that of its companions), a position (though again, it will almost certainly differ in its position from the others), and a text label (e.g., “OK”, “Cancel,” and “Help”). Likewise, all three buttons will have common behaviors, such as the ability to be drawn, activated, pressed, and so forth. Thus, the details might differ among the individual buttons, but they are all of the same type.
As in many object-oriented programming languages, in C# a type is
defined by a class
, while the individual
instances of that class are known as objects.
Later chapters will explain that there are other types in C# besides
classes, including enums, structs, and delegates, but for now the
focus is on classes.
The “Hello World” program declares a single type: the
HelloWorld
class. To define a C# type, you declare
it as a class using the
class
keyword, give it a
name—in this case, HelloWorld
—and then
define its properties and behaviors. The property and behavior
definitions of a C# class must be enclosed by open and closed braces
({}
).
A class has both properties and behaviors. Behaviors are defined with member methods; properties are discussed in Chapter 3.
A method is a
function
owned by your class. In fact, member methods are sometimes called
member functions.
The member methods define what your
class can do or how it behaves. Typically, methods are given action
names, such as WriteLine()
or
AddNumbers()
. In the case shown here, however, the
class method has a special name, Main( )
, which
doesn’t describe an action but does designate to the
Common Language Runtime (CLR) that
this is the main, or first method, for your class.
Unlike C++, Main
is capitalized in C# and can
return int
or void
.
The CLR calls Main( )
when your program starts.
Main( )
is the entry point for your program, and
every C# program must have a Main( )
method.[4]
Method declarations are a contract between the creator of the method and the consumer (user) of the method. It is possible, even likely, that the creator and consumer will be the same programmer, but this does not have to be so; it is possible that one member of a development team creates the method and another programmer consumes (or uses) it.
To declare a method, you specify a return value type followed by a name. Method declarations also require parentheses, whether the method accepts parameters or not. For example:
int myMethod(int size );
declares a method named myMethod
that takes one
parameter: an integer which will be referred to within the method as
size. My method returns an integer value. The
return value type tells the consumer of the method what kind of data
the method will return when it finishes running.
Some methods do not return a value at all; these are said to return
void
, which is specified by the
void
keyword. For
example:
void myVoidMethod( );
declares a method that returns void
and takes no
parameters. In C# you must always declare a return type or
void
.
A C# program can also contain comments. Take a look at the first line after the opening brace:
// Use the system console object
The text begins with two forward
slash marks (//
).
These designate a comment. A comment is a note
to the programmer and does not affect how the program runs. C#
supports three types of comments.
The first type, shown here, indicates that all text to the right of the comment mark is to be considered a comment, until the end of that line. This is known as a C++ style comment.
The second type of comment, known as a C-Style
comment
, begins with an
open comment mark (/*
) and ends with a closed
comment mark (*/
). This allows comments to span
more than one line without having to have //
characters at the beginning of each comment line, as shown in Example 2-2.
Example 2-2. Illustrating multiline comments
class Hello { static void Main( ) { /* Use the system console object as explained in the text in chapter 2 */ System.Console.WriteLine("Hello World"); } }
It is possible to nest C++ style comments within C-style comments. For this reason, it is common to use C++ style comments whenever possible, and to reserve the C-style comments for “commenting-out” blocks of code.
The third and final type of comment that C# supports is used to associate external XML-based documentation with your code, and is illustrated in Chapter 13.
“Hello World” is an example of a console program. A console application has no user interface (UI); there are no list boxes, buttons, windows, and so forth. Text input and output is handled through the standard console (typically a command or DOS window on your PC). Sticking to console applications for now helps simplify the early examples in this book, and keeps the focus on the language itself. In later chapters, we’ll turn our attention to Windows and web applications, and at that time we’ll focus on the Visual Studio .NET UI design tools.
All that the
Main( )
method does in this simple example is write the text “Hello
World” to the monitor. The monitor is managed by an object
named Console
. This Console
object has a method WriteLine( )
which takes a
string (a set of characters) and writes it to
the standard output. When you run this program, a command or DOS
screen will pop up on your computer monitor and display the words
“Hello World.”
You invoke a method with the dot operator
(.
). Thus, to call the
Console
object’s WriteLine( )
method, you write
Console.WriteLine(...)
, filling in the string to
be printed.
Console
is only one of a
tremendous number of useful types that are part of the .NET
Framework Class Library (FCL). Each class
has a name, and thus the FCL contains thousands of names, such as
ArrayList
, Dictionary
,
FileSelector
, DataError
,
Event
, and so on. Names and names; hundreds,
thousands, even tens of thousands of names.
This presents a problem. No developer can possibly memorize all the
names that the .NET Framework uses, and sooner or later you are
likely to create an object and give it a name that has already been
used. What will happen if you develop your own
Dictionary
class, only to discover that it
conflicts with the Dictionary
class that .NET
provides? Remember, each class in C# must have a unique name.
You certainly could rename your Dictionary
class
mySpecialDictionary
, for example, but that is a
losing battle. New Dictionary
types are likely to
be developed, and distinguishing between their type names and yours
would be a nightmare.
The solution to this problem is to create a
namespace
. A namespace restricts a name’s
scope, making it meaningful only within the defined namespace.
Assume that I tell you that Jim is an engineer. The word “engineer” is used for many things in English, and can cause confusion. Does he design buildings? Write software? Run a train?
In English I might clarify by saying “he’s a
scientist,” or “he’s a train engineer.” A C#
programmer could tell you that Jim is a
science.engineer
rather than a
train.engineer
. The namespace (in this case,
science
or train
) restricts the
scope of the word which follows. It creates a “space” in
which that name is meaningful.
Further, it might happen that Jim is not just any kind of
science.engineer
. Perhaps Jim graduated from MIT
with a degree in software engineering, not civil engineering (are
civil engineers especially polite?). Thus, the object that is
Jim
might be defined more specifically as a
science.software.engineer
. This classification
implies that the namespace software
is meaningful
within the namespace science
, and that
engineer
in this context is meaningful within the
namespace software
. If later you learn that
Charlotte is a transportation.train.engineer
, you
will not be confused as to what kind of engineer she is. The two uses
of engineer
can coexist, each within its own
namespace.
Similarly, if you learn that .NET has a Dictionary
class within its System.Collections
namespace, and
that I have also created a Dictionary
class within
a ProgCSharp.DataStructures
namespace, there is no
conflict because each exists in its own namespace.
In Example 2-1, the Console
object’s name is restricted to the System
namespace by using the code:
System.Console.WriteLine( )
In Example 2-1, the
dot operator
(.
) is used both to access a method (and data) in
a class (in this case, the method WriteLine( )
),
and to restrict the class name to a specific namespace (in this case,
to locate Console
within the System
namespace). This works well because in
both cases we are “drilling down” to find the exact thing
we want. The top level is the System
namespace
(which contains all the System
objects that the
Framework provides); the Console
type exists
within that namespace, and the WriteLine( )
method is a member function of the
Console
type.
In many cases, namespaces are divided into subspaces. For example,
the System
namespace contains a number of
subnamespaces such as
Configuration
,
Collections
, Data,
and so
forth, while the Collections
namespace itself is
divided into multiple subnamespaces.
Namespaces can help you organize and compartmentalize your types. When you write a complex C# program, you might want to create your own namespace hierarchy, and there is no limit to how deep this hierarchy can be. The goal of namespaces is to help you divide and conquer the complexity of your object hierarchy.
Rather than
writing the word System
before
Console
, you could specify that you will be using
types from the System
namespace by writing the statement:
using System;
at the top of the listing, as shown in Example 2-3.
Example 2-3. The using keyword
using System; class Hello { static void Main( ) { //Console from the System namespace Console.WriteLine("Hello World"); } }
Notice that the using System
statement is placed before the
HelloWorld
class definition.
Although you can designate that you are using the
System
namespace, unlike with some languages you
cannot designate that you are using the
System.Console
object. Example 2-4 will not compile.
Example 2-4. Code that does not compile (not legal C#)
using System.Console; class Hello { static void Main( ) { //Console from the System namespace WriteLine("Hello World"); } }
This generates the compile error:
error CS0138: A using namespace directive can only be applied to namespaces; 'System.Console' is a class not a namespace
The using
idiom can save a great deal of typing,
but it can undermine the advantages of namespaces by polluting the
namespace with many undifferentiated names. A common solution is to
use the using
keyword with the built-in namespaces
and with your own corporate namespaces, but perhaps not with
third-party components.
C# is
case-sensitive,
which means that writeLine
is not the same as
WriteLine
, which in turn is not the same as
WRITELINE
. Unfortunately, unlike in Visual Basic
(VB), the C# development environment will not fix your case mistakes;
if you write the same word twice with different cases, you might
introduce a tricky-to-find bug into your program.
To prevent such a time-wasting and energy-depleting mistake, you
should develop conventions for naming your variables, functions,
constants, and so forth. The convention in this book is to name
variables with camel notation (e.g.,
someVariableName
), and to name functions,
constants, and properties with Pascal notation (e.g.,
SomeFunction
).
The Main( )
method shown
in Example 2-1 has one more designation. Just before
the return type declaration void
(which, you will
remember, indicates that the method does not return a value)
you’ll find the keyword static
:
static void Main( )
The static
keyword indicates that you can invoke
Main( )
without first creating an object of type
Hello
. This somewhat complex issue will be
considered in much greater detail in subsequent chapters. One of the
problems with learning a new computer language is you must use some
of the advanced features before you fully understand them. For now,
you can treat the declaration of the Main( )
method as tantamount to
magic.
[4] It is technically possible to have multiple
Main( )
methods in C#; in that case you use the
/main
compiler directive to tell C# which class
contains the Main( )
method that should serve as
the entry point to the program.
18.216.96.94