Bill Blogs in C#

Bill Wagner discusses C#, LINQ, and other items of interest

February 2005 - Posts

Those of you that receive .NET Insight saw this yesterday

Fawacette Technical Publications (FTP) has published a second excerpt from Effective C# online. This time it's Item 44, discussing how to create your own custom exception classes.



The landing page at FTP
This is where you can retrieve both excerpts
The Effective C# Home page
Addison Wesley's page on Effective C#.

Posted by wwagner | with no comments
Filed under:
A reader asked why the VS.NET debugger sometimes stops execution of your program for an exception that you don't create. The debugger sees exceptions generated in the framework too.

I received this question via email recently, and I thought the answer would be of general interest:

We are currently working through a book study on the Effective C# book and I have come across an "issue" I was hoping you could help me understand....it is funny since I spent a number of hours working through this EXACT issue in my application, and then I went home that night to ready the chapters for the book study and you described the exact issue.  Unfortunately the example code is showing the same problem as my application.

This sample piece of code below will throw a "First Chance Exception" (in the IDE with all exceptions turned on under the Debug/Exceptions menu) if the file does NOT exist....I can NOT catch the exception in a try/catch block AND the code continues to execute normally after that (and the file is even created!!)....kinda weird.  I took this code "directly" from Item 47

 static void Main(string[] args)
{
IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForDomain();
  // This next line causes a "first chance exception" if the file does NOT exist,
//
but then it creates the file anyways..
  IsolatedStorageFileStream myStream =
new IsolatedStorageFileStream("FredTest.txt", FileMode.Create, iso);
}

Here’s my answer: 

The IsolatedStorageFileStream constructor generates and catches the exception when the file does not exist.

That’s why you see it in the debugger, when “stop on all exceptions” is set. The framework does catch the exception, and creates the missing file system resources. That’s why the code runs correctly, even though it does generate the exceptions. That’s why I usually try to run the IDE where it only stops on exceptions that are uncaught, rather than all exceptions. At times, stopping on all exceptions is just not practical. NUnit is another example: it generates a number of exceptions when it loads, but it catches them all.

(For those of you following along at home (using Reflector or ILDASM), examine IsolatedStorageFile.Init() for the particular try / catch block involved in this example.)



Posted by wwagner | with no comments
Filed under:
The Connecticut .NET Developer's Group is live

A little while ago, S.B. Chatterjee, webmaster for the Connecticut .NET Developer's Association, asked our local user group for help setting up his website.  Our webmaster, Patrick Steele helped him get up and running.  The results are here.  They look great, and we're happy to help another user group get off the ground.



GANG
The Great Lakes .NET User Group
The Connecticut .NET Developer's Assocation
Another net .NET user group
Patrick Steele
The Great Lakes .NET User Group
S.B. Chatterjee's blog
Connecticut .NET Developer Group Webmaster
Posted by wwagner | with no comments
Filed under:
and I'm looking forward to being in the Louisville area

Tim Landgrave was kind enough to invite me to speak at the Kentucky .NET Developer's Association.  I'm busily working on the slide deck, and the right set of interesting and fun samples.

I'm also trying to figure out how to fit in a side visit to Loretto KY to visit Maker's Mark.



The announcement at the Kentucky Users Group
I just hope I live up to the billing
Addison Wesley also made an announcement
Oh, and you can buy Effective C# from this page
Maker's Mark Home
Yes, I plan to try and stop by
Posted by wwagner | with no comments
SQLConnection, for one, calls GC.SuppressFinalization() in its constructor. Why would you do that?

A fried of mine asked about the practice of calling GC.SuppressFinalize() in a constructor. He noticed it in the SQLConnection constructor. It’s also present in a number of other components, such as the Windows Forms Datagrid. Is it safe? Why do it?

Calling GC.SuppressFinalize() is a performance optimization that a number of classes that derive from System.ComponentModel.Component use. Personally, I think it can be unsafe, so adopt it with caution.

System.ComponentModel.Component implements IDisposable and provides a finalizer so that all derived classes can cleanup both managed and unmanaged resources.

The pertinent pieces of code are here:

// IDisposable.Dispose:
// delegates the work to Dispose( bool )
// Then, notify the GC that Finalization is no longer needed.
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}

// Finalizer.
// Delegates the work to Dispose( bool )
~Component()
{
this.Dispose(false);
}





// hook for all derived classes:
protected virtual void Dispose(bool disposing) {
// KEY POINT: If called from the finalizer,
// there's nothing to do.
if (!disposing)
{
return;
}
// much other work elided
}

SQLConnection overrides Dispose( bool ) to close the connection when IDisposable.Dispose() is called:

protected override void Dispose(bool disposing) {
if (disposing)
{
switch (this._objectState)
{
case ConnectionState.Open:
{
this.Close();
break;
}
}
this._constr = null;
}
// KEY POINT: Note that there is no 'else' clause.
// No work gets done when called by the finalizer.
base.Dispose(disposing);
}

Just like in Component, nothing actually happens when this is called from the Finalizer. That means the finalizer for SQLConnection doesn't really need to be called under any circumstances, even when the user forgets to call IDisposable.Dispose()

Well, Finalizers extract a rather heavy performance penalty on the garbage collector. And, sometimes people forget using clauses, or calling Dispose() diligently. So, the constructor for SQLConnection calls GC.SuppressFinalization( this ) so that the GC ignores the presence of the finalizer, and you don't need to pay the performance penalty if you forget to call IDisposable.Dispose().

This technique is correct only because:

  1. SQLConnection is sealed, so no one can create a class derived from SQLConnection that actually does work when the finalizer executes.
  2. SQLConnection, and all base classes: System.ComponentModel.Component, System.MarshalByRefObject, and System.Object do not perform any cleanup in their finalizers.

The reason I find this a bit unsafe is that it's entirely possible for someone to add code breaking (2) above in some future release. I don't advocate it for general use. But, SQLConnection gets used a lot, and here, the performance costs probably add up. And, hopefully, if one of the base classes does make that change, everyone gets notified.

I'll close with my own question: Why doesn't SQLConnection need to do any work in its finalizer? Once again, if you use Reflector, you'll see quite a bit of code in the Close() method. What happens if that never gets called? If you know, please contact me.



Implement the Standard Dispose Idiom
I covered this in depth in Effective C#
Posted by wwagner | with no comments
Filed under: ,
I've been getting quite a few questions about smart client development with Pocket PC, so here's some resources

It must be time for people to work on pocket pc / Compact Framework development.  I've been getting a number of questions recently about best practices for Smart Client development on the Pocket PC.

There are a wealth of resources out there to help. Here are a few that help on most of common questions:

. How do I connect to a SQL database from my PocketPC application?  How do I know when my PocketPC gets connected to the cradle, so I should synchronize with the server?  (See IBuySpy Delivery below.)

. How do I write a disconnect application that uses a web service to communicate with the server?  (See TaskVision below)

. How best to create multiple-form applications? should I create multiple modal forms?  Should I hide forms to show new ones?  Use tabs?  What?  (See FotoVision).  The difficulty is a much smaller screen puts a premium on how you use the space, and the PocketPC treats minimize and close as "hide and deactivate".  It will make you change quite a bit on how you work with your applications.

And, of course, see OpenNETCF for quite a few libraries and samples



TaskVision Pocket PC architecture guide
Remember the TaskVision sample from DevDays? Here's a version for mobile devices. It shows how to create an application that communicates via Web Services.
IBuySpy Deliver -- 2005 Version
IBuySpy deliver shows how to communicate via SQL RDA, or Merge Replication. This is the 2005 version.
IBuySpy Delivery -- 2003 Version
This version runs in the 1.1 version of the .NET Framework
FotoVision
The FotoVision sample shows some of the best practices for PocketPC UIs
OpenNETCF
A wealth of resources and libraries for Compact Framework Development
Posted by wwagner | with no comments
Filed under: