楼主: bnso

Introduction to C# Programming

[复制链接]
论坛徽章:
49
NBA季后赛之星
日期:2014-10-19 19:51:33蓝锆石
日期:2014-10-19 19:51:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33问答徽章
日期:2014-04-15 10:41:44优秀写手
日期:2014-07-24 06:00:11保时捷
日期:2014-10-19 19:51:33三菱
日期:2014-10-19 19:51:33
121#
 楼主| 发表于 2006-8-13 21:40 | 只看该作者
36 Module 9: Creating and Destroying Objects
7. Add two accessor methods, called Amount and When, that return the
values of the two instance variables:
private readonly decimal amount;
private readonly DateTime when;
...
public decimal Amount( )
{
return amount;
}
public DateTime When( )
{
return when;
}
? To create the constructor
1. Define a public constructor for the BankTransaction class. It will take a
decimal parameter called tranAmount that will be used to populate the
amount instance variable.
2. In the constructor, initialize when with DateTime.Now.
DateTime.Now is a property and not a method, so you do not need to
use parentheses.
The completed constructor is as follows:
public BankTransaction(decimal tranAmount)
{
amount = tranAmount;
when = DateTime.Now;
}
3. Compile the project and correct any errors.
? To create transactions
1. As described above, transactions will be created by the BankAccount class
and stored in a queue whenever the Deposit or Withdraw method is
invoked. Return to the BankAccount class.
2. Before the start of the BankAccount class, add the following using
directive:
using System.Collections;
3. Add a private instance variable call tranQueue to the BankAccount class.
Its data type should be Queue and it should be initialized with a new empty
queue:
private Queue tranQueue = new Queue( );
Tip
Module 9: Creating and Destroying Objects 37
4. In the Deposit method, before returning, create a new transaction using the
deposit amount as the parameter, and append it to the queue by using the
Enqueue method, as follows:
public decimal Deposit(decimal amount)
{
accBal += amount;
BankTransaction tran = new BankTransaction(amount);
tranQueue.Enqueue(tran);
return accBal;
}
5. In the Withdraw method, if there are sufficient funds, create a transaction
and append it to tranQueue as in the Deposit method, as follows:
public bool Withdraw(decimal amount)
{
bool sufficientFunds = accBal >= amount;
if (sufficientFunds) {
accBal -= amount;
BankTransaction tran = new BankTransaction(-amount);
tranQueue.Enqueue(tran);
}
return sufficientFunds;
}
For the Withdraw method, the value passed to the constructor of the
BankTransaction should be the amount being withdrawn preceded by the
negative sign.
Note
38 Module 9: Creating and Destroying Objects
? To test transactions
1. For testing purposes, add a public method called Transactions to the
BankAccount class. Its return type should be Queue , and the method
should return tranQueue. You will use this method for displaying
transactions in the next step. The method will be as follows:
public Queue Transactions( )
{
return tranQueue;
}
2. In the CreateAccount class, modify the Write method to display the details
of transactions for each account. Queues implement the IEnumerable
interface, which means that you can use the foreach construct to iterate
through them.
3. In the body of the foreach loop, print out the date and time and the amount
for each transaction, by using the When and Amount methods, as follows:
static void Write(BankAccount acc)
{
Console.WriteLine("Account number is {0}",
acc.Number( ));
Console.WriteLine("Account balance is {0}",
acc.Balance( ));
Console.WriteLine("Account type is {0}", acc.Type( ));
Console. WriteLine("Transactions:";
foreach (BankTransaction tran in acc.Transactions( ))
{
Console.WriteLine("Date/Time: {0}\tAmount: {1}",
êtran.When( ), tran.Amount( ));
}
Console.WriteLine( );
}
4. In the Main method, add statements to deposit and w ithdraw money from
each of the four accounts (acc1, acc2, acc3, and acc4).
5. Compile the project and correct any errors.
6. Execute the project. Examine the output and check whether transactions are
displayed as expected.
Module 9: Creating and Destroying Objects 39
u Objects and Memory
n Object Lifetime
n Objects and Scope
n Garbage Collection
In this section, you will learn what happens when an object, as opposed to a
value, goes out of scope or is destroyed and about the role of garbage collection
in this process.

使用道具 举报

回复
论坛徽章:
49
NBA季后赛之星
日期:2014-10-19 19:51:33蓝锆石
日期:2014-10-19 19:51:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33问答徽章
日期:2014-04-15 10:41:44优秀写手
日期:2014-07-24 06:00:11保时捷
日期:2014-10-19 19:51:33三菱
日期:2014-10-19 19:51:33
122#
 楼主| 发表于 2006-8-13 21:41 | 只看该作者
40 Module 9: Creating and Destroying Objects
Object Lifetime
n Creating Objects
l You allocate memory by using new
l You initialize an object in that memory by using a
constructor
n Using Objects
l You call methods
n Destroying Objects
l The object is converted back into memory
l The memory is deallocated
In C#, destroying an object is a two-step process that corresponds to and
reverses the two-step object creation process.
Creating Objects
In the first section, you learned that creating a C# object for a reference type is
a two-step process, as follows:
1. Use the new keyword to acquire and allocate memory.
2. Call a constructor to turn the raw memory acquired by new into an object.
Destroying Objects
Destroying a C# object is also a tw o-step process:
1. De-initialize the object.
This converts the object back into raw memory. It is done by the destructor
or the Finalize method. This is the reverse of the initialization performed by
the constructor. You can control what happens in this step by writing your
own destructor or finalize method.
2. The raw memory is deallocated; that is, it is given back to the memory heap.
This is the reverse of the allocation performed by new. You cannot change
the behavior of this step in any way.
Module 9: Creating and Destroying Objects 41
Objects and Scope
n The Lifetime of a Local Value Is Tied to the Scope in
Which It Is Declared
l Short lifetime (typically)
l Determinisitic creation and destruction
n The Lifetime of a Dynamic Object Is Not Tied to Its
Scope
l A longer lifetime
l A non-deterministic destruction
Unlike values such as ints and structs, which are allocated on the stack and are
destroyed at the end of their scope, objects are allocated on the heap and are not
destroyed at the end of their scope.
Values
The lifetime of a local value is tied to the scope in which it is declared. Local
values are variables that are allocated on the stack and not through the new
operator. This means that if you declare a variable whose type is one of the
primitives (such as int), enum, or struct, you cannot use it outside the scope in
which you declare it. For example, in the following code fragment, three values
are declared inside a for statement, and so go out of scope at the end of the for
statement:
struct Point { public int x, y; }
enum Season { Spring, Summer, Fall, Winter }
class Example
{
void Method( )
{
for (int i = 0; i < limit; i++) {
int x = 42;
Point p = new Point( );
Season s = Season.Winter;
}
x = 42; // Compile-time error
p = new Point( ); // Compile-time error
s = Season.Winter; // Compile-time error
}
}

使用道具 举报

回复
论坛徽章:
49
NBA季后赛之星
日期:2014-10-19 19:51:33蓝锆石
日期:2014-10-19 19:51:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33问答徽章
日期:2014-04-15 10:41:44优秀写手
日期:2014-07-24 06:00:11保时捷
日期:2014-10-19 19:51:33三菱
日期:2014-10-19 19:51:33
123#
 楼主| 发表于 2006-8-13 21:41 | 只看该作者
42 Module 9: Creating and Destroying Objects
In the previous example, it appears as though a new Point is created.
However, because Point is a struct, new does not allocate memory from the
heap. The “new” Point is created on the stack.
This means that local values have the following characteristics:
n Deterministic creation and destruction
A local variable is created when you declare it, and is destroyed at the end
of the scope in which it is declared. The start point and the end point of the
value’s life are deterministic; that is, they occur at known, fixed times.
n Usually very short lifetimes
You declare a value somewhere in a method, and the value cannot exist
beyond the method call. When you return a value from a method, you return
a copy of the value.
Objects
The lifetime of an object is not tied to the scope in which it is created. Objects
are initialized in heap memory allocated through the new operator. For example,
in the following code, the reference variable eg is declared inside a for
statement. This means that eg goes out of scope at the end of the for statement
and is a local variable. However, eg is initialized with a new Example() object,
and this object does not go out of scope with eg. Remember: a reference
variable and the object it references are different things.
class Example
{
void Method( )
{
for (int i = 0; i < limit; i++) {
Example eg = new Example( );
...
}
// eg is out of scope
// Does eg still exist?
// Does the object still exist?
}
}
This means that objects typically have the following characteristics:
n Non-deterministic destruction
An object is created when you create it, but, unlike a value, it is it not
destroyed at the end of the scope in which it is created. The creation of an
object is deterministic, but the destruction of an object is not. You cannot
control exactly when an object will be destroyed.
n Longer lifetimes
Because the life of an object is not tied to the method that creates it, an
object can exist well beyond a single method call.
Note
Module 9: Creating and Destroying Objects 43
Garbage Collection
n You Cannot Destroy Objects in C#
l C# does not have an opposite of new (such as delete)
l This is because an explicit delete function is a prime
source of errors in other languages
n Garbage Collection Destroys Objects for You
l It finds unreachable objects and destroys them for you
l It finalizes them back to raw unused heap memory
l It typically does this when memory becomes low
So far, you have seen that you create objects in C# in exactly the same way that
you create objects in other languages, such as C++. You use the new keyword
to allocate memory from the heap, and you call a constructor to convert that
memory into an object. However, as far as the method for the destruction of
objects, there is no similarity between C# and its predecessors.
You Cannot Destroy Objects in C#
In many programming languages, you can explicitly control when an object will
be destroyed. For example, in C++ you can use a delete expression to deinitialize
(or finalize) the object (turn it back into raw memory) and then return
the memory to the heap. In C#, there is no way to explicitly destroy objects. In
many ways, this restriction is a useful one because programmers often misuse
the ability to explicitly destroy objects by:
n Forgetting to destroy objects.
If you had the responsibility for writing the code that destroyed an object,
you might sometimes forget to write the code. This can happen in C++ code,
and this is a problematic bug that causes the user’s computer to get slower
as the program uses more memory. This is known as memory leak. Often the
only way to reclaim the lost memory is to shut down and then restart the
offending program.
n Attempting to destroy the same object more than once.
You might sometimes accidentally attempt to destroy the same object more
than once. This can happen in C++ code, and it is a serious bug with
undefined consequences. The problem is that when you destroy the object
the first time, the memory is reclaimed and can be used to create a new
object, probably of a completely different class. When you then attempt to
destroy the object the second time, the memory refers to a completely
different object!

使用道具 举报

回复
论坛徽章:
49
NBA季后赛之星
日期:2014-10-19 19:51:33蓝锆石
日期:2014-10-19 19:51:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33问答徽章
日期:2014-04-15 10:41:44优秀写手
日期:2014-07-24 06:00:11保时捷
日期:2014-10-19 19:51:33三菱
日期:2014-10-19 19:51:33
124#
 楼主| 发表于 2006-8-13 21:41 | 只看该作者
44 Module 9: Creating and Destroying Objects
n Destroying an active object.
You might sometimes destroy an object that was still being referred to in
another part of the program. This is also a serious bug known as the
dangling pointer problem, and it also has undefined consequences.
Garbage Collection Destroys Objects for You
In C#, you cannot destroy an object explicitly in code. Instead, C# has a
garbage collection, which destroys objects for you. Garbage collection is
completely automatic. It ensures that:
n Objects are destroyed.
However, garbage collection does not specify exactly when the object will
be destroyed.
n Objects are destroyed only once.
This means that you cannot get the undefined behavior of double deletion
that is possible in C++. This is important because it helps to ens ure that a C#
program always behaves in a well-defined way.
n Only unreachable objects are destroyed.
Garbage collection ensures that an object is never destroyed if another
object holds a reference to it. Garbage collection only destroys an object
when no other object holds a reference to it. The ability of one object to
reach another object through a reference variable is called reachability.
Only unreachable objects are destroyed. It is the function of garbage
collection to follow all of the object references to determine which objects
are reachable and hence, by a process of elimination, to find the remaining
unreachable objects. This can be a time-consuming operation, so garbage
collection only collects garbage to reclaim unused memory when memory
becomes low.
You can also invoke garbage collection explicitly in your code, but it is
not recommended. Let the .NET runtime manage memory for you.
Note
Module 9: Creating and Destroying Objects 45
u Using Destructors
n The Finalize Method
n Writing Destructors
n Destructors and the Finalize Method
n Warnings About Destructor Timing
n GC.SuppressFinalize( )
n Using the Disposal Design Pattern
n Using IDisposable
A destructor is a special method that you use to de-initialize an object. In this
section, you will learn how to use destructors and the Finalize method to
control the destruction of object.
This course is based on the Beta 1 version of Microsoft Visual
Studio.NET. In Beta 2 and subsequent versions of Visual Studio.NET,
destructors will always be executed, even if it is only at the end of the program.
This feature is not available in Beta 1.
Note

使用道具 举报

回复
论坛徽章:
49
NBA季后赛之星
日期:2014-10-19 19:51:33蓝锆石
日期:2014-10-19 19:51:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33问答徽章
日期:2014-04-15 10:41:44优秀写手
日期:2014-07-24 06:00:11保时捷
日期:2014-10-19 19:51:33三菱
日期:2014-10-19 19:51:33
125#
 楼主| 发表于 2006-8-13 21:41 | 只看该作者
46 Module 9: Creating and Destroying Objects
The Finalize Method
n The Final Actions of Different Objects Will Be Different
l They cannot be determined by garbage collection
l You can write an optional Finalize method
l If present, garbage collection will call Finalize before
reclaiming the raw memory
l Finalize is the opposite of a constructor and must have
the following syntax:
pprrootteecctteedd oovveerrrriiddee vvooiidd FFiinnaalliizzee(( )) {{ }}
You have already seen that destroying an object is a two-step process. In the
first step, the object is converted back into raw memory. In the second step, the
raw memory is returned to the heap to be recycled. Garbage collection
completely automates the second step of this process for you.
However, the actions required to finalize a specific object back into raw
memory to clean it up will depend on the specific object. This means that
garbage collection cannot automate the first step for you. If there are any
specific statements that you want an object to execute as it is picked up by
garbage collection and just before its memory is reclaimed, you need to write
these statements yourself in a method called Finalize.
Finalization
When garbage collection is destroying an unreachable object, it will check
whether the class of the object has its own Finalize method. If the class has a
Finalize method, it will call the method before recycling the memory back to
the heap. The statements you write in the Finalize method will be specific to
the class, but the signature of the Finalize method must take a particular form:
n No arguments required
Remember, you do not call Finalize ; garbage collection does.
n void return type
The purpose of Finalize is not to return a result but to perform an action.
You might think it reasonable for Finalize to return a bool to indicate
whether the object was successfully finalized. The problem with this
approach is that it would not really help. When does garbage collection call
Finalize, and what would it return any value to?
Module 9: Creating and Destroying Objects 47
n Use override modifier
All classes inherit from the Object class. The Object class has a virtual
method called Finalize. Your Finalize must override Object.Finalize . This
will become clearer after you have learned about inheritance and
polymorphism.
n Protected access
Finalize in the Object base class has protected access, and when you
override a method you are not allowed to change that method’s access. This
will become clearer after you have completed Module 10, “Inheritance in
C#.”
The following code shows an example of the SourceFile class with an
embedded StreamReader whose Finalize method closes the StreamReader:
class SourceFile
{
public SourceFile(string name)
{
File src = new File(name);
reader = src.OpenText( );
}
...
protected override void Finalize( )
{
reader.Close( );
}
...
private StreamReader reader;
}

使用道具 举报

回复
论坛徽章:
49
NBA季后赛之星
日期:2014-10-19 19:51:33蓝锆石
日期:2014-10-19 19:51:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33问答徽章
日期:2014-04-15 10:41:44优秀写手
日期:2014-07-24 06:00:11保时捷
日期:2014-10-19 19:51:33三菱
日期:2014-10-19 19:51:33
126#
 楼主| 发表于 2006-8-13 21:42 | 只看该作者
48 Module 9: Creating and Destroying Objects
Writing Destructors
n A Destructor Is an Alternative to Finalize
l It has its own syntax:
- no access modifier
- no return type, not even void
- same name as name of class with leading ~
- no parameters
class SourceFile
{
~SourceFile( ) { ... }
}
class SourceFile
{
~SourceFile( ) { ... }
}
You can write a destructor as an alternative to the Finalize method. The
relationship between Finalize and the destructor is extremely close and is
explained in detail in the next topic. The Finalize method and destructors share
the following features:
n No access modifier
You do not call the destructor; garbage collection does.
n No return type
The purpose of the destructor is not to return a value but to perform the
required clean-up actions.
n No parameters can be passed
Again, you do not call the destructor, so you cannot pass it any arguments.
Note that this means that the destructor cannot be overloaded.
Module 9: Creating and Destroying Objects 49
Destructors and the Finalize Method
n The Compiler Will Automatically Convert a Destructor
into a Finalize Method
class SourceFile
{
~SourceFile( ) { Console.WriteLine("Dying"; }
public void Test( ) { Finalize( ); }
}
class SourceFile
{
~SourceFile( ) { Console.WriteLine("Dying"; }
public void Test( ) { Finalize( ); }
}
class SourceFile
{
~SourceFile( ) { }
protected void Finalize( ) { }
}
class SourceFile
{
~SourceFile( ) { }
protected void Finalize( ) { }
}
Will this compile without error?
What happens when you call Test?
When you write a destructor for a class, the compiler will automatically convert
that destructor into a Finalize method for that class. A Finalize method
generated from a destructor and a Finalize method that you have written
yourself are almost identical. In particular, garbage collection treats them the
same.
One important difference between them is that a destructor will be converted
into a Finalize method that automatically calls Finalize on its base class.
Question 1
Examine the following code. Will it compile without error?
class SourceFile
{
~SourceFile( ) { }
protected void Finalize( ) { }
}
The code example will generate an error when compiled. The destructor is
converted into a Finalize method that has no arguments. This means that after
the compiler conversion has taken place, there will be two methods called
Finalize that expect no arguments. This is not allowed and will cause the
compiler to generate a “duplicate definition” diagnostic message.

使用道具 举报

回复
论坛徽章:
49
NBA季后赛之星
日期:2014-10-19 19:51:33蓝锆石
日期:2014-10-19 19:51:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33问答徽章
日期:2014-04-15 10:41:44优秀写手
日期:2014-07-24 06:00:11保时捷
日期:2014-10-19 19:51:33三菱
日期:2014-10-19 19:51:33
127#
 楼主| 发表于 2006-8-13 21:42 | 只看该作者
50 Module 9: Creating and Destroying Objects
Question 2
Examine the following code. What will happen when you call Test?
class SourceFile
{
~SourceFile( )
{
...
Console.WriteLine("Dying";
}
public void Test( )
{
Finalize( );
}
}
To answer this question, remember that the compiler will convert the destructor
into a Finalize method. In other words, the above example will become the
following:
class SourceFile
{
protected void override Finalize( )
{
...
Console.WriteLine("Dying";
}
public void Test( )
{
Finalize( );
}
}
This means that when you call Test, the Console.WriteLine statement inside
the destructor will be executed, writing “Dying” to the console.
This second question also shows that you can explicitly call the
Finalize method on an object. But remember, garbage collection will also call
the Finalize method on the object when the object is garbage collected, leading
to the same object being finalized more than once! The solution to this multiple
finalization problem is covered later in this section.
You cannot declare destructors or Finalize methods in structs.
Important
Note
Module 9: Creating and Destroying Objects 51
Warnings About Destructor Timing
n You Cannot Rely on Destructors Being Called
l Garbage collection is only called if memory becomes low
l What if memory never becomes low?
n The Order of Destruction Is Undefined
l Not necessarily the reverse order of construction
You have seen that in C# garbage collection is responsible for destroying
objects when they are unreachable. This is unlike other languages such as C++,
in which the programmer is responsible for explicitly destroying objects.
Shifting the responsibility for destroying objects away from the programmer is
a good thing, but it you cannot control exactly when a C# object is destroyed.
This is sometimes referred to as non-deterministic finalization.
You Cannot Rely on Destructors Being Called
When garbage collection is called upon to destroy some objects, it must find the
objects that are unreachable, call their Finalize methods (if they have them),
and then recycle their memory back to the heap. This is a complicated process
(the details of which are beyond the scope of this course), and it takes a fair
amount of time. Consequently, garbage collection does not run unless it needs
to (and when it does it runs in its own thread).
The one time when garbage collection must run is when the heap runs out of
memory. But this means that if your program starts, runs, and then shuts down
without getting close to using the entire heap, your Finalize methods may never
get called, and if they do, it will only be when the program shuts down. In many
cases, this is perfectly acceptable. However, there are situations in which you
must ensure that your Finalize methods are called at known points in time. You
will learn how to deal with these situations later in this section.
52 Module 9: Creating and Destroying Objects
The Order of Destruction Is Undefined
In languages like C++, you can explicitly control when objects are created and
when objects are destroyed. In C#, you can control the order in which you
create objects but you cannot control the order in which they are destroyed.
This is because you do not destroy the objects at all— garbage collection does.
In C#, the order of the creation of objects does not determine the order of the
destruction of those objects. They can be destroyed in any order, and many
other objects might be destroyed in between. However, in practice this is rarely
a problem because garbage collection guarantees that an object will never be
destroyed if it is reachable. If one object holds a reference to a second object,
the second object is reachable from the first object. This means that the second
object will never be destroyed before the first object.

使用道具 举报

回复
论坛徽章:
49
NBA季后赛之星
日期:2014-10-19 19:51:33蓝锆石
日期:2014-10-19 19:51:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33问答徽章
日期:2014-04-15 10:41:44优秀写手
日期:2014-07-24 06:00:11保时捷
日期:2014-10-19 19:51:33三菱
日期:2014-10-19 19:51:33
128#
 楼主| 发表于 2006-8-13 21:42 | 只看该作者
Module 9: Creating and Destroying Objects 53
GC.SuppressFinalize( )
n You Can Explicitly Call Finalize on an Object
l This can sometimes be useful
n If You Call Finalize, Garbage Collection Will Call It Again
When It Collects the Object
l To prevent this, suppress finalization if you explicitly call
Finalize
class GC
{
...
public static void SuppressFinalize(Object o)...
}
class GC
{
...
public static void SuppressFinalize(Object o)...
}
GC is part of the .NET SDK
You can explicitly call the Finalize method, but this creates a potential problem.
If an object has a Finalize method, garbage collection will see it and will also
call it when it destroys the object. The following code provides an example:
class DoubleFinalization
{
~DoubleFinalization( )
{
...
}
public void Dispose( )
{
Finalize( );
}
...
}
54 Module 9: Creating and Destroying Objects
The problem with this example is that if you call Dispose, it will call Finalize
(generated from the destructor). Then, when the object is garbage collected,
Finalize will be called again.
To avoid duplicate finalization, you can call the SuppressFinalize method of
the GC class and pass in the object that already had its Finalize method called.
The following code provides an example:
class SingleFinalization
{
~SingleFinalization( )
{
...
}
public void Dispose( )
{
Finalize( );
GC.SuppressFinalize(this);
}
...
}
There are several more problems related to this technique. These
problems are explored in the next topic.
Note

使用道具 举报

回复
论坛徽章:
49
NBA季后赛之星
日期:2014-10-19 19:51:33蓝锆石
日期:2014-10-19 19:51:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33问答徽章
日期:2014-04-15 10:41:44优秀写手
日期:2014-07-24 06:00:11保时捷
日期:2014-10-19 19:51:33三菱
日期:2014-10-19 19:51:33
129#
 楼主| 发表于 2006-8-13 21:42 | 只看该作者
Module 9: Creating and Destroying Objects 55
Using the Disposal Design Pattern
n To Reclaim a Resource:
l Provide a public method (often called Dispose) that calls
Finalize and then suppresses finalization
l Ensure that calling Dispose more than once is benign
l Ensure that you do not try to use a reclaimed resource
If you need to reclaim a resource and you cannot wait for garbage collection to
call Finalize implicitly for you, you can provide a public method that calls
Finalize.
Memory Is Not the Only Resource
Memory is the most common resource that your programs use, and you can rely
on garbage collection to reclaim unreachable memory when the heap becomes
low. However, memory is not the only resource. Other fairly common resources
that your program might use include file handles and mutex locks. Often these
other kinds of resources are in much more limited supply than memory, or need
to be released quickly.
The Disposal Method Design Pattern
In these situations, you cannot rely on garbage collection to perform the release
by means of a Finalize method, because, as you have seen, you cannot know
when garbage collection will call Finalize. Instead, you should write a public
method that releases the resource, and then make sure to call this method at the
right point in the code. These methods are called Disposal Methods. (This is a
well-known pattern, but it is not in Design Patterns: Elements of Reusable
Object-Oriented Software.) In C#, there are three major points that you need to
remember when implementing a Disposal Method:
n Remember to call SuppressFinalize.
n Ensure that the Disposal Method can be called repeatedly.
n Avoid using a released resource.
56 Module 9: Creating and Destroying Objects
Calling SuppressFinalize
The following code shows how to call SuppressFinalize :
class Example
{
...
~Example( )
{
rare.Dispose( );
}
public void Dispose( )
{
Finalize( );
GC.SuppressFinalize(this);
}
...
private Resource rare = new Resource( );
}
Calling the Disposal Method Multiple Times
Remember, the Disposal Method is public, so it can be called repeatedly. The
easiest way to make sure multiple calls are possible is with a simple bool field.
The following code provides an example:
class Example
{
...
~Example( )
{
disposed = true;
rare.Dispose( );
}
public void Dispose( )
{
if (!disposed) {
Finalize( );
GC.SuppressFinalize(this);
}
}
...
private Resource rare = new Resource( );
private bool disposed = false;
}

使用道具 举报

回复
论坛徽章:
49
NBA季后赛之星
日期:2014-10-19 19:51:33蓝锆石
日期:2014-10-19 19:51:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33指数菠菜纪念章
日期:2014-10-19 19:52:33问答徽章
日期:2014-04-15 10:41:44优秀写手
日期:2014-07-24 06:00:11保时捷
日期:2014-10-19 19:51:33三菱
日期:2014-10-19 19:51:33
130#
 楼主| 发表于 2006-8-13 21:43 | 只看该作者
Module 9: Creating and Destroying Objects 57
Avoiding the Use of Released Resources
The easiest way to do avoid using released resources is to reset the reference to
null in Finalize and check for null in each method, as follows:
class Example
{
...
~Example( )
{
rare.Dispose( );
rare = null;
disposed = true;
}
public void Dispose( )
{
if (!disposed) {
Finalize( );
GC.SuppressFinalize(this);
}
}
public void Use( )
{
if (!disposed) {
Wibble w = rare.Stuff( );
...
} else {
throw new DisposedException( );
}
}
private Resource rare = new Resource( );
private bool disposed = false;
}
58 Module 9: Creating and Destroying Objects
Using IDisposable
n If Any Method Throws an Exception
l Subsequent statements may not be executed
l Resources may not be released by your code
n Use try-finally Blocks Carefully
n A Proposed Modification to C# Handles This By:
l Extending the using statement to indicate resource use
l Providing the IDisposable interface that declares a
Dispose method, for use by resource classes
When writing disposal code, it is important to be aware of the some of the
common programming errors. For example, there is a dispose method trap that
is quite common. Look at the following code, and decide whether reader.Close
(whic h is a Disposal Method that reclaims a scarce file handle) is called.
class SourceFile
{
public SourceFile(string name)
{
File src = new File(name);
contents = new char[(int)src.Length];
StreamReader reader = src.OpenText( );
reader.ReadBlock(contents, 0, contents.Length);
reader.Close( );
}
...
private char[ ] contents;
}

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表