Chapter 3
discusses
the myriad primitive types built into the C# language, such as
int
, long
, and
char
. The heart and soul of C#, however, is the
ability to create new, complex, programmer-defined types that map
cleanly to the objects that make up the problem you are trying to
solve.
It is this ability to create new types that characterizes an object-oriented language. You specify new types in C# by declaring and defining classes. You can also define types with interfaces, as you will see in Chapter 8. Instances of a class are called objects. Objects are created in memory when your program executes.
The difference between a class and an object is the same as the difference between the concept of a Dog and the particular dog who is sitting at your feet as you read this. You can’t play fetch with the definition of a Dog, only with an instance.
A Dog
class describes what dogs are like: they
have weight, height, eye color, hair color, disposition, and so
forth. They also have actions they can take, such as eat, walk, bark,
and sleep. A particular dog (such as my dog Milo) will have a
specific weight (62 pounds), height (22 inches), eye color (black),
hair color (yellow), disposition (angelic), and so forth. He is
capable of all the actions of any dog (though if you knew him you
might imagine that eating is the only method he implements).
The huge advantage of classes in object-oriented programming is that they encapsulate the characteristics and capabilities of an entity in a single, self-contained and self-sustaining unit of code. When you want to sort the contents of an instance of a Windows list box control, for example, you tell the list box to sort itself. How it does so is of no concern; that it does so is all you need to know. Encapsulation, along with polymorphism and inheritance, is one of three cardinal principles of object-oriented programming.
An old programming joke asks, how many object-oriented programmers does it take to change a light bulb? Answer: none, you just tell the light bulb to change itself. (Alternate answer: none, Microsoft has changed the standard to darkness.)
This chapter explains the C# language features that are used to
specify new classes. The elements of a class—its behaviors and
properties—are known collectively as its class
members.
This chapter will
show how methods are used to define the behaviors of the class, and
how the state of the class is maintained in member variables (often
called
fields
).
In addition, this chapter introduces
properties
,
which act like methods to the creator of the class but look like
fields to clients of the class.
To define
a new type or class you first declare it, and then define its methods
and fields. You declare a class using the class
keyword. The complete syntax is as follows:
[attributes
] [access-modifiers
] classidentifier
[:base-class
] {class-body
}
Attributes are covered in Chapter 18; access
modifiers are discussed in the next section. (Typically, your classes
will use the keyword
public
as an access modifier.) The identifier
is the name of the class that you provide. The
optional base-class
is discussed in Chapter 5. The member definitions that make up the
class-body
are enclosed by open and closed
curly
braces ({}
).
Tip
C++ programmers take note: a C# class definition does not end with a semicolon, though if you add one the program will still compile.
In C#, everything happens within a class. For instance, some of the
examples in Chapter 3 make use of a class named
Tester
:
public class Tester
{
public static int Main( )
{
/...
}
}
So far, we’ve not instantiated
any
instances of that class; that is, we haven’t created any
Tester
objects. What is the difference between a
class and an instance of that class? To answer that question, start
with the distinction between the type
int
and a
variable
of type int
. Thus, while you would write:
int myInteger = 5;
you would not write:
int = 5;
You can’t assign a value to a type; instead, you assign the
value to an object of that type (in this case, a variable of type
int
).
When you declare a new class, you define the properties of all objects of that class, as well as their behaviors. For example, if you are creating a windowing environment, you might want to create screen widgets, more commonly known as controls in Windows programming, to simplify user interaction with your application. One control of interest might be a list box, a control that is very useful for presenting a list of choices to the user and enabling the user to select from the list.
List boxes have a variety of characteristics: height, width, location, and text color, for example. Programmers have also come to expect certain behaviors of list boxes: they can be opened, closed, sorted, and so on.
Object-oriented programming allows you to create a new
type, ListBox,
which
encapsulates these characteristics and capabilities. Such a class
might have member variables named height
,
width
, location,
and
text color
, and member methods named
sort()
, add()
, remove( )
, etc.
You can’t assign data to the ListBox
type.
Instead you must first create an object of that type, as in the
following code snippet:
ListBox myListBox;
Once you create an instance of ListBox
, you can
assign data to its fields.
Now consider a class to keep track of and display the time of day. The internal state of the class must be able to represent the current year, month, date, hour, minute, and second. You probably would also like the class to display the time in a variety of formats. You might implement such a class by defining a single method and six variables, as shown in Example 4-1.
Example 4-1. Simple Time class
using System;
public class Time
{
// public methods
public void DisplayCurrentTime( )
{
Console.WriteLine(
"stub for DisplayCurrentTime");
}
// private variables
int Year;
int Month;
int Date;
int Hour;
int Minute;
int Second;
}
public class Tester
{
static void Main( )
{
Time t = new Time( );
t.DisplayCurrentTime( );
}
}
The only method declared within the Time
class
definition is the method DisplayCurrentTime( )
.
The body of the method is defined within the class definition itself.
Unlike other languages (such as C++), C# does not require that
methods be declared before they are defined, nor does the language
support placing its declarations into one file and code into another.
(C# has no header files.) All C# methods are defined in line as shown
in Example 4-1 with DisplayCurrentTime( )
.
The DisplayCurrentTime( )
method is defined to
return void
; that is, it will not return a value
to a method that invokes it. For now, the body of this method has
been “stubbed out.”
The Time
class definition ends with the
declaration of a number of member variables: Year
,
Month
, Date
,
Hour
, Minute
, and
Second
.
After the closing brace, a second class, Tester
,
is defined. Tester
contains our now familiar
Main( )
method. In Main( )
an instance of
Time
is created and its address is assigned to
object t
. Because t
is an
instance of Time
, Main( )
can
make use of the DisplayCurrentTime( )
method
available with objects of that type and call it to display the time:
t.DisplayCurrentTime( );
An access modifier determines which class methods—including methods of other classes—can see and use a member variable or method within a class. Table 4-1 summarizes the C# access modifiers.
Table 4-1. Access modifiers
Access Modifier |
Restrictions |
---|---|
No restrictions. Members marked | |
The members in class A which are marked | |
The members in class A which are marked | |
The members in class A which are marked | |
|
The members in class A which are marked |
It is generally desirable to designate the member variables of a
class as private
. This means that only member
methods of that class can access their value. Because
private
is the default accessibility level, you do
not need to make it explicit, but I recommend that you do so. Thus,
in Example 4-1, the declarations of member variables
should have been written as follows:
// private variables private int Year; private int Month; private int Date; private int Hour; private int Minute; private int Second;
Class Tester
and method
DisplayCurrentTime()
are both declared
public
so that any other class can make use of
them.
Methods
can take any number of
parameters.[6] The
parameter list follows the method name and is encased in parentheses,
with each parameter preceded by its type. For example, the following
declaration defines a method named MyMethod
which
returns void
(that is, which returns no value at
all) and which takes two parameters: an int
and a
button:
void MyMethod (int firstParam, button secondParam) { // ... }
Within the body of the method, the parameters act as local variables,
as if you had declared them in the body of the method and initialized
them with the values passed in. Example 4-2
illustrates how you pass values into a method, in this case values of
type int
and float
.
Example 4-2. Passing values into SomeMethod( )
using System; public class MyClass { public void SomeMethod(int firstParam, float secondParam) { Console.WriteLine( "Here are the parameters received: {0}, {1}", firstParam, secondParam); } } public class Tester { static void Main( ) { int howManyPeople = 5; float pi = 3.14f; MyClass mc = new MyClass( ); mc.SomeMethod(howManyPeople, pi); } }
The method SomeMethod( )
takes an
int
and a
float
and displays them using
Console.WriteLine( )
. The parameters, which are
named firstParam
and
secondParam
, are treated as local variables within
SomeMethod( )
.
In the calling method (Main
), two local variables
(howManyPeople
and pi)
are
created and initialized. These variables are passed as the parameters
to SomeMethod( )
. The compiler maps
howManyPeople
to firstParam
and
pi
to secondParam
, based on
their relative positions in the parameter list.
[6] The terms “argument” and “parameter” are often used interchangeably, though some programmers insist on differentiating between the argument declaration and the parameters passed in when the method is invoked.
Get Programming C# now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.