Initializing Objects
Most of the time when you create an object, you need to initialize its properties. You generally
wouldnt create an
Employee object without at least setting its FirstName and LastName prop-
erties. The following code shows how you might initialize an
Employee object:
// Make an Employee named Alice.
Employee alice = new Employee();
alice.FirstName = “Alice”;
alice.LastName = “Archer”;
alice.Street = “100 Ash Ave”;
alice.City = “Bugsville”;
alice.State = “CO”;
alice.Zip = “82010”;
alice.EmployeeId = 1001;
alice.MailStop = “A-1”;
Though this is relatively straightforward, it is a bit tedious. Creating and initializing a bunch
of
Employees would take a lot of repetitive code. Fortunately C# provides alternatives that
make this task a little easier.
In this lesson you learn how to initialize an object’s properties as you create it. You also learn
how to make constructors that make initializing objects easier, and how to make destructors
that clean up after an object.
INITIALIZING OBJECTS
C# provides a simple syntax for initializing an objects properties as you create it. Create the
object as usual but follow the
new keyword and the classs name with braces. Inside the braces,
place comma-separated statements that initialize the object’s properties.
For example, the following code creates an
Employee object named Bob. The statements inside
the braces initialize the object’s properties.
// Make an Employee named Bob.
Employee bob = new Employee()
{
24
596906c24.indd 289 4/7/10 12:33:52 PM
290
LESSON 24 InItIalIzIng Objects
FirstName = “Bob”,
LastName = “Baker”,
Street = “200 Beach Blvd”,
City = “Bugsville”,
State = “CO”,
Zip = “82010”,
EmployeeId = 1002,
MailStop = “B-2”
};
Note that an initializer can only initialize properties that the code can access.
For example, if a property is private, the initializer cannot set its value.
CONSTRUCTORS
Initializers are handy and easy to use but sometimes you might like some extra control over how an
object is created. Constructors give you that extra control.
A constructor is a routine that is executed when an object is created. The constructor executes before
the code that creates the object gets hold of it. The constructor can perform any setup tasks that you
want to get the object ready to use. It can look up data in databases, prepare data structures, and ini-
tialize properties.
The next two sections describe two kinds of constructors: parameterless constructors and param-
eterized constructors. The section after those explains how one constructor can invoke another to
avoid duplicated work.
Parameterless Constructors
A constructor can take parameters just like any other method to help it in its setup tasks. A param-
eterless constructor takes no parameters, so it’s somewhat limited in what it can do.
Parameterless constructors are also sometimes called empty constructors.
When you first create a class, C# defines a parameterless constructor for it called
the default constructor. If you create your own parameterless constructor, the
default constructor is not created.
For example, suppose the Manager class has a DirectReports property, which is a list of Employees
that report to a given manager. A parameterless constructor cannot build that list because it doesnt
596906c24.indd 290 4/7/10 12:33:52 PM
Constructors
291
know what employees to put in it. It can, however, initialize the DirectReports to an empty list as
shown in the following code:
class Manager : Person
{
List<Employee> DirectReports;
// Initialize the Manager.
public Manager()
{
DirectReports = new List<Employee>();
}
}
You implicitly invoke a parameterless constructor any time you create an object without using any
parameters. For example, the following code creates a new
Person object. When this code executes,
control jumps briefly to the parameterless constructor so it can prepare the object for use.
Person Fred = new Person();
Note that C# creates a default public parameterless constructor for you if you make a class that doesn’t
define any constructors explicitly. If you do give the class any constructors, however, C# doesn’t create
the default constructor. In that case, if you want a parameterless constructor, you must make it yourself.
Parameterized Constructors
Parameterless constructors are useful but fairly limited because they don’t have much information
to go by. To give a constructor more information, you can make it take parameters just like you can
with any other method.
One simple type of parameterized constructor uses its parameters to initialize properties. For example,
you could make a constructor for the
Person class that takes the person’s first and last names as
parameters. The constructor could then set the object’s
FirstName and LastName properties.
Why would you bother doing this when you could use an initializer? First, the syntax for using a
constructor is slightly more concise than initializer syntax. The following code uses a constructor
that takes eight parameters to initialize an
Employees properties:
Employee bob = new Employee(“Bob”, “Baker”, “200 Beach Blvd”,
“Bugsville”, “CO”, “82010”, 1002, “B-2”);
Compare this code to the earlier snippet that used initializers. This version is more concise, although
it’s less self-documenting because it doesn’t explicitly list the property names.
The second reason you might prefer to use a parameterized constructor instead of an initializer is that
a constructor can perform all sorts of checks that an initializer cannot. For example, a constructor can
validate its parameters against each other or against a database. An
Employee class’s constructor could
take an employee ID as a parameter and check in a database to verify that the employee really exists.
A constructor can also require that certain parameters be provided. For example, a
Person constructor
could require that the first and last name parameters be provided. If you rely on initializers, the pro-
gram could create a
Person that has no first or last name.
596906c24.indd 291 4/7/10 12:33:52 PM
292
LESSON 24 InItIalIzIng Objects
To make a constructor that takes parameters, simply add the parameters as you would for any other
method. The following code shows a constructor for the
Person class that uses its parameters to
initialize the new
Person object’s properties:
// Make an Employee named Cindy.
Person cindy = new Person(“Cindy”, “Carstairs”,
“1750 Cedar Ct”, “Bugsville”, “CO”, “82010”);
DESTRUCTORS
Constructors execute when a new object is created to perform initialization chores. Destructors
execute when an object is being destroyed to perform cleanup chores. For example, a destructor
might close database connections, close files, free memory, and do whatever else is necessary before
the object gets carted off to the electronic recycle center.
Destructors are simpler than constructors because:
A class can have only one destructor.
You cannot call a destructor directly; they are only called automatically.
A destructor cannot invoke another destructor.
Destructors cannot take parameters.
The following code shows a simple destructor for the Person class:
~Person()
{
// Perform cleanup chores here...
}
Destructors are a fairly specialized topic and you are unlikely to need to build one until you have
more experience programming, but I wanted to describe them for an important reason: so you know
when destructors execute and you can help them perform well.
You might think that so far destructors are fairly simple and that would be the end of the story
except for one remaining question: “When are destructors called?” This turns out to be a trickier
question than you might imagine. To understand when a destructor runs, you need to understand
the garbage collector.
Normally a C# program runs merrily along, creating variables and objects as needed. Sometimes all
of the references to an object disappear so the program no longer has access to the object. In that
case, the memory (and any other resources) used by that object are lost to the program.
If the program makes a lot of objects and then discards them in this way, the program will eventually
use up a lot of memory.
Eventually the program may start to run out of memory. At that point, the garbage collector springs
into action. The garbage collector runs when it thinks the program may have used a lot of inaccessible
memory such as these
Employee objects. When the garbage collector runs, it reclaims the memory
wasted by objects that are inaccessible and makes that memory available for future objects.
596906c24.indd 292 4/7/10 12:33:52 PM
Destructors
293
It is only when the garbage collector reclaims an object’s memory that the object’s destructors
execute. So the answer to the question “When are destructors called?” is: “Whenever the gar-
bage collector runs.” So when does the garbage collector run? The answer to this new question is:
“Whenever it feels like it.
The end result is that you cannot really know when a destructor will run. The fancy name for this is
non-deterministic finalization. Many programs never run low on memory so the garbage collector
doesnt run until the program ends.
The moral of the story is that you can use destructors to clean up after an object but you shouldn’t
rely on them to handle tasks that must be done in a timely fashion. For example, if a destructor
closes a file so other programs can use it, the file may not actually be closed until the program ends.
If you want to perform actions such as this in a timely fashion, give the class a
CleanUp or Dispose
function that the program can call explicitly to take care of business.
The IDisposable interface formalizes the notion of providing a Dispose
method that cleans up an object. It’s a fairly advanced topic, however, so it isn’t
covered here. For more information, see
msdn.microsoft.com/en-us/library/
b1yfkh5e%28VS.71%29.aspx
and msdn.microsoft.com/en-us/library/system
.idisposable.aspx
.
If an object does provide a Dispose method, you should probably use it when you are done with the
object. To prevent you from forgetting to call
Dispose, C# provides the using statement.
The
using statement is followed by the object that it manages and, when the using block ends, the
program automatically calls the object’s
Dispose method.
The usual syntax for a
using block is:
using (variableInitialization)
{
... Statements ...
}
In this syntax, the variableInitialization declares and initializes the variable that the block
controls. (You can declare the object outside of the
using block but putting it inside the block usu-
ally makes it easier to read and restricts its scope to the block.)
For example, the
Graphics class uses system resources that should be released when you’re done
with a Graphics object so it provides a
Dispose method. The following code creates a Graphics
object named
gr associated with the bitmap bigBitmap. The using block ensures that the program
executes the
gr object’s Dispose method when it finishes the block.
using (Graphics gr = Graphics.FromImage(bigBitmap))
{
// Draw stuff...
}
596906c24.indd 293 4/7/10 12:33:53 PM
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.22.58