Top Ten Traps In C# For C++ Programmers
05.22.03

By Jessie Liberty

In an article for the July 2001 MSDN Magazine I talked about what you need to know to move from C++ to C#. In that article, I mentioned that the syntax of C# is very similar to that of C++ and that the difficult part of the transition was not the language itself but getting comfortable with the managed environment of .NET and understanding the extensive .NET Framework.

I’ve begun to compile a list of the syntactical differences that exist between C++ and C#. (See the FAQ from my book, Programming C#, at www.LibertyAssociates.com.) As you might expect, most of the syntactic changes are small and nearly trivial. There are, however, some changes that are potential traps for the unwary C++ programmer, and this article will focus on the ten most dangerous.

Trap #1: Nondeterministic finalization and the C# destructor
The biggest difference in C# for most C++ programmers will be garbage collection. You will no longer have to worry about memory leaks and ensuring that pointers are deleted, but you also give up precise control over when your objects will be destroyed.

If you control an unmanaged resource, however, you will need to explicitly free that resource when you are done with it. Implicit control over unmanaged resources is provided by a destructor, which will be called by the garbage collector when your object is destroyed.

The destructor should only release unmanaged resources that your object holds on to, and it should not reference other objects. If you have only managed references you do not need to (and should not) implement a destructor. You want this only for handling unmanaged resources. Because there is some cost to having a destructor, you ought to implement this only on methods that consume valuable, unmanaged resources.

You never call an object’s destructor directly. The garbage collector will call it for you.

How destructors work

The garbage collector maintains a list of objects that have a destructor. This list is updated every time such an object is created or destroyed.

When an object on this list is first collected, it is placed on a queue with other objects waiting to be destroyed. After the destructor executes, the garbage collector then collects the object and updates the queue, as well as its list of destructible objects.

The C# destructor

C#’s destructor looks, syntactically, much like a C++ destructor, but it behaves quite differently. You declare a C# destructor with a tilde as follows:

~MyClass ( ) { }

In C#, however, this syntax is simply a shortcut for declaring a Finalize() method that chains up to its base class. Thus, when you write:

~MyClass()
{
// do work here
}


the C# compiler translates it to:

protected override void Finalize()
{
try
{
// do work here
}
finally
{
base.Finalize();
}
}


Trap #2: Finalize versus Dispose

It is not legal to call a destructor explicitly. Your destructor will be called by the garbage collector. If you do handle precious unmanaged resources (such as file handles) that you want to close and dispose of as quickly as possible, you ought to implement the IDisposable interface. The IDisposable interface requires its implementers to define one method, named Dispose(), to perform whatever cleanup you consider to be crucial. The availability of Dispose() is a way for your clients to say, "Don’t wait for the destructor to be called; do it right now."

Programming Resource Downloads



If you provide a Dispose() method, you should stop the garbage collector from calling your object’s destructor. To stop the garbage collector, you call the static method, GC.SuppressFinalize(), passing in this reference for your object. Your destructor can then call your Dispose() method. Thus, you might write:

using System;
class Testing : IDisposable
{
bool is_disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!is_disposed) // only dispose once!
{
if (disposing)
{
Console.WriteLine("Not in destructor, OK to reference
other objects");
}
// perform cleanup for this object
Console.WriteLine("Disposing...");
}
this.is_disposed = true;
}
public void Dispose()
{
Dispose(true);
// tell the GC not to finalize
GC.SuppressFinalize(this);
}
~Testing()
{
Dispose(false);
Console.WriteLine("In destructor.");
}
}


Implementing the Close method

For some objects, you’d rather have your clients call the Close() method. (For example, Close makes more sense than Dispose() for file objects.) You can implement this by creating a private Dispose()method and a public Close() method and having your Close() method invoke Dispose().

Click here to read the full article



About the Author:
Jesse Liberty is the best selling author of Programming ASP.NET, Programming C#, and a dozen other books on web and object oriented programming. He is president of Liberty Associates, Inc., where he provides contract programming, consulting and on-site training in ASP.NET, C#, C++ and related topics. Jesse has been a Distinguished Software Engineer at AT&T and Vice President for technology development at CitiBank.


XML Data Tools

SecureXML Digital Signature
XML is being used to create standard document types that represent the electronic equivalent of physical documents.

XMLwriter 2.1
Advanced JPEG Compressor for Windows is an invaluable and useful tool for everyone who knows what is a digital image.

 

 

 




 

 

 

 

 

 

 

-- CProgrammingTrends is an iEntry, Inc. publication --
2003 iEntry, Inc. All Rights Reserved Privacy Policy  Legal