Chapter 8
Class Methods
In This Chapter
ᮣ
Passing an object to a function
ᮣ
Converting a class function into a method
ᮣ
What is
this
?
ᮣ
Creating the best documentation in town (I know, but I made it)
T
his chapter moves from the static functions discussed in Chapter 7 to
nonstatic methods of a class. Static functions belong to the whole class,
while methods belong to each instance created from the class. By the way,
many programmers choose to call everything a method or everything a func-
tion rather than making the distinction as I have. But there are important dif-
ferences between static and nonstatic class members.
Passing an Object to a Function
You pass object references as arguments to functions in the same way that
you pass value-type variables, with one difference: You always pass objects
by reference.
The following small program demonstrates how you pass objects — to func-
tions, that is:
// PassObject - demonstrate how to pass an object
// to a function
using System;
namespace PassObject
{
public class Student
{
public string sName;
}
public class Program
{
14_597043 ch08.qxd 9/20/05 1:59 PM Page 163
public static void Main(string[] args)
{
Student student = new Student();
// set the name by accessing it directly
Console.WriteLine(“The first time:”);
student.sName = “Madeleine”;
OutputName(student);
// change the name using a function
Console.WriteLine(“After being modified:”);
SetName(student, “Willa”);
OutputName(student);
// wait for user to acknowledge
Console.WriteLine(“Press Enter to terminate...”);
Console.Read();
}
// OutputName - output the student’s name
public static void OutputName(Student student)
{
// output current student’s name
Console.WriteLine(“Student’s name is {0}”, student.sName);
}
// SetName - modify the student object’s name
public static void SetName(Student student, string sName)
{
student.sName = sName;
}
}
}
The program creates a
student
object consisting of nothing but a name.
(We like to keep ’em simple down here.) The program first sets the name of
the
student
directly and passes it to the output function
OutputName()
.
OutputName()
displays the name of any
Student
object it receives.
The program then updates the name of the
student
by calling
SetName()
.
Because all reference-type objects are passed by reference in C#, the changes
made to
student
are retained back in the calling function. When
Main()
out-
puts the
student
object again, the name has changed, as shown in the fol-
lowing code:
The first time:
Student’s name is Madeleine
After being modified:
Student’s name is Willa
Press Enter to terminate...
The
SetName()
function can change the name within the
Student
object and
make it stick.
164
Part III: Object-Based Programming
14_597043 ch08.qxd 9/20/05 1:59 PM Page 164
Notice that you don’t use the
ref
keyword when passing a reference-type
object. Yet the effect is that the object’s contents can be modified through the
reference. However, if
OutputName()
tried to assign a whole new
Student
object to its
Student
parameter, this wouldn’t affect the original
Student
object outside the function, as the following code shows:
Student student = new Student();
student.Name = “Madeleine”;
OutputName(student);
Console.WriteLine(student.Name); // still “Madeleine”
...
// a revised OutputName():
public static void OutputName(Student student)
{
student = new Student(); // doesn’t replace student outside OutputName()
student.Name = “Pam”;
}
Defining Object Functions and Methods
A class is supposed to collect the elements that describe a real-world object
or concept. For example, a
Vehicle
class may contain data elements for max-
imum velocity, weight, carrying capacity, and so on. However, a
Vehicle
has
active properties as well: the ability to start, to stop, and the like. These are
described by the functions that go with that vehicular data. These functions
are just as much a part of the
Vehicle
class as the data elements.
Defining a static member function
For example, you could rewrite the program from the previous section in a
slightly better way as follows:
// PassObjectToMemberFunction - rely upon static member functions
// to manipulate fields within the object
using System;
namespace PassObjectToMemberFunction
{
public class Student
{
public string sName;
// OutputName - output the student’s name
public static void OutputName(Student student)
165
Chapter 8: Class Methods
14_597043 ch08.qxd 9/20/05 1:59 PM Page 165
{
// output current student’s name
Console.WriteLine(“Student’s name is {0}”, student.sName);
}
// SetName - modify the student object’s name
public static void SetName(Student student, string sName)
{
student.sName = sName;
}
}
public class Program
{
public static void Main(string[] args)
{
Student student = new Student();
// set the name by accessing it directly
Console.WriteLine(“The first time:”);
student.sName = “Madeleine”;
Student.OutputName(student);
// change the name using a function
Console.WriteLine(“After being modified:”);
Student.SetName(student, “Willa”);
Student.OutputName(student);
// wait for user to acknowledge
Console.WriteLine(“Press Enter to terminate...”);
Console.Read();
}
}
}
This program has only one significant change from the
PassObject
program
in the previous section: I put the
OutputName()
and
SetName()
functions in
the
Student
class.
Because of that change,
Main()
must reference the
Student
class in the calls
to
SetName()
and
OutputName()
. The functions are now members of the
class
Student
and not
Program
, the class in which
Main()
resides.
This is a small but significant step. Placing
OutputName()
within the class
leads to a higher level of reuse: Outside functions that need to display the
object can find
OutputName()
, along with other output functions, right there
as part of the class. It doesn’t have to be written separately by each program
using the
Student
class.
This is also a better solution on a philosophical level. Class
Program
shouldn’t
need to worry about how to initialize the name of a
Student
object nor about
how to output important material. The
Student
class should contain that
information. Objects are responsible for themselves.
In fact,
Main()
should not initialize the name to Madeleine in the first place.
It should call
SetName()
instead.
166
Part III: Object-Based Programming
14_597043 ch08.qxd 9/20/05 1:59 PM Page 166
From within
Student
, one member function can invoke another without
explicitly applying the class name.
SetName()
could invoke
OutputName()
without needing to reference the class name. If you leave off the class name,
C# assumes that the function being accessed is in the same class.
Defining a method
The data members of an object — an instance of a class — are accessed with
the object and not with the class. Thus, you may say the following:
Student student = new Student(); // create an instance of Student
student.sName = “Madeleine”; // access the member via the instance
C# enables you to invoke nonstatic member functions in the same way:
student.SetName(“Madeleine”);
The following example demonstrates this technique:
// InvokeMethod - invoke a member function through the object
using System;
namespace InvokeMethod
{
class Student
{
// the name information to describe a student
public string sFirstName;
public string sLastName;
// SetName - save off name information (no longer static)
public void SetName(string sFName, string sLName)
{
sFirstName = sFName;
sLastName = sLName;
}
// ToNameString - convert the student object into a
// string for display (not static)
public string ToNameString()
{
string s = sFirstName + “ “ + sLastName;
return s;
}
}
public class Program
{
public static void Main()
{
Student student = new Student();
student.SetName(“Stephen”, “Davis”);
Console.WriteLine(“Student’s name is “
167
Chapter 8: Class Methods
14_597043 ch08.qxd 9/20/05 1:59 PM Page 167
+ student.ToNameString());
// wait for user to acknowledge
Console.WriteLine(“Press Enter to terminate...”);
Console.Read();
}
}
}
The output from this program is this simple line:
Student’s name is Stephen Davis
Other than having a much shorter name, this program is very similar to the
earlier
PassObjectToMemberFunction
program. This version uses nonstatic
functions to manipulate both a first and a last name.
The program begins by creating a new
Student
object,
student
. The pro-
gram then invokes the
SetName()
function, which stores the two
string
s
“Stephen”
and
“Davis”
into the data members
sFirstName
and
sLastName
.
Finally, the program calls the member function
ToNameString()
, which
returns the name of the
student
by concatenating the two
string
s.
For historical reasons that have nothing to do with C#, a nonstatic member
function is commonly known as a method. I use the term method for nonstatic
member functions, and I use function for all other types. Some programmers
use the terms instance method (nonstatic) and class method (static).
Look again at the
SetName()
method that updates the first and last name
fields in the
Student
object. Which object does
SetName()
modify? Consider
the following example to see how it works:
Student christa = new Student(); // here’s one student
Student sarah = new Student(); // and here’s a completely different one
christa.SetName(“Christa”, “Smith”);
sarah.SetName(“Sarah”, “Jones”);
The first call to
SetName()
updates the first and last name of the
christa
object. The second call updates the
sarah
object.
Thus, C# programmers say that a method operates on the current object. In
the first call, the current object is
christa
; in the second, it’s
sarah
.
Expanding a method’s full name
A subtle but important problem exists with my description of method names.
To see the problem, consider the following example code snippet:
168
Part III: Object-Based Programming
14_597043 ch08.qxd 9/20/05 1:59 PM Page 168
public class Person
{
public void Address()
{
Console.WriteLine(“Hi”);
}
}
public class Letter
{
string sAddress;
// save off the address
public void Address(string sNewAddress)
{
sAddress = sNewAddress;
}
}
Any subsequent discussion of the
Address()
method is now ambiguous. The
Address()
method within
Person
has nothing to do with the
Address()
method in
Letter
. If my programmer friend tells me to access the
Address()
method, which
Address()
does he mean?
The problem lies not with the methods themselves, but with my description.
In fact, no
Address()
method exists as an independent entity — only a
Person.Address()
and a
Letter.Address()
method. Attaching the class
name to the beginning of the method name clearly indicates which method is
intended.
This description is very similar to people’s names. Within my family, I am
known as Stephen. (Actually, within my family, I am known by my middle
name, but you get the point.) There are no other Stephens within my family
(at least not within my close family). However, there are two other Stephens
where I work.
If I’m at lunch with some coworkers and the other two Stephens aren’t pre-
sent, the name Stephen clearly refers to me. Back in the trenches (or cubi-
cles), yelling out “Stephen” is ambiguous because it could refer to any one of
us. In that context, you need to yell out “Stephen Davis” as opposed to
“Stephen Williams” or “Stephen Leija.”
Thus, you can consider
Address()
to be the first name or nickname of a
method, with its class as the family name.
Accessing the Current Object
Consider the following
Student.SetName()
method:
169
Chapter 8: Class Methods
14_597043 ch08.qxd 9/20/05 1:59 PM Page 169
class Student
{
// the name information to describe a student
public string sFirstName;
public string sLastName;
// SetName - save off name information
public void SetName(string sFName, string sLName)
{
sFirstName = sFName;
sLastName = sLName;
}
}
public class Program
{
public static void Main()
{
Student student1 = new Student();
student1.SetName(“Joseph”, “Smith”);
Student student2 = new Student();
student2.SetName(“John”, “Davis”);
}
}
The function
Main()
uses the
SetName()
method to update first
student1
and then
student2
. But you don’t see a reference to either
Student
object
within
SetName()
itself. In fact, no reference to a
Student
object exists. A
method is said to operate on “the current object.” How does a method know
which one is the current object? Will the real current object please stand up?
The answer is simple. The current object is passed as an implicit argument in
the call to a method — for example:
student1.SetName(“Joseph”, “Smith”);
This call is equivalent to the following:
Student.SetName(student1, “Joseph”, “Smith”); // equivalent call
// (but this won’t build properly)
I’m not saying you can invoke
SetName()
in two different ways, just that the
two calls are semantically equivalent. The object identifying the current
object — the hidden first argument — is passed to the function, just like
other arguments. Leave that up to the compiler.
Passing an object implicitly is pretty easy to swallow, but what about a refer-
ence from one method to another? The following code illustrates calling one
method from another:
170
Part III: Object-Based Programming
14_597043 ch08.qxd 9/20/05 1:59 PM Page 170
public class Student
{
public string sFirstName;
public string sLastName;
public void SetName(string sFirstName, string sLastName)
{
SetFirstName(sFirstName);
SetLastName(sLastName);
}
public void SetFirstName(string sName)
{
sFirstName = sName;
}
public void SetLastName(string sName)
{
sLastName = sName;
}
}
No object appears in the call to
SetFirstName()
. The current object contin-
ues to be passed along silently from one method call to the next. An access to
any member from within an object method is assumed to be with respect to
the current object. The upshot is that a method “knows” which object it
belongs to.
What is the this keyword?
Unlike most arguments, the current object does not appear in the function
argument list, so it is not assigned a name by the programmer. Instead, C#
assigns this object the not-very-imaginative name
this
, useful in the few situ-
ations where you need to refer directly to the current object.
this
is a C# keyword, and it may not be used for any other purpose, at least
not without the express written permission of the National Football League.
Thus, you could write the previous example as follows:
public class Student
{
public string sFirstName;
public string sLastName;
public void SetName(string sFirstName, string sLastName)
{
// explicitly reference the “current object” referenced by this
this.SetFirstName(sFirstName);
this.SetLastName(sLastName);
171
Chapter 8: Class Methods
14_597043 ch08.qxd 9/20/05 1:59 PM Page 171