Bill Blogs in C#

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

December 2004 - Posts

Quote: "Why should a developer building "business solutions" ever care about closing a connection to a database, or even opening it?"

Eugenio has an interesting take on IDisposable, or the needs for business developers to actually care about resource acquisition or release.  He sez:

"The "using" statement is one step forward, but not enough in my opinion. In the same way you need to remember closing a connection, you need to remember using "using"."

Interesting stuff. I'm not sure the problem is as big as he makes it out though.  If you forget to close, or Dispose something, it's likely more of a performance error than a resource leak.  Eventually, the finalizer will clean up.  (Yes, I can construct code that makes it a fatal bug, but it's not often occurring in practice.)

It would be nice to create a class that had deterministic finalization, when needed though.



Eugenio's post
More on IDisposable.
Posted by wwagner | with no comments
Filed under: ,
Jeff Julian and John Alexander are hard at work.

Jeff Julian, and John Alexander are hard at work to re-launch two book sites aimed at developers. Jeff describes the current strategy here.

I think it’s cool enough that I’ve agreed to do a web cast for them based on material from Effective C#. The details (like the date) are still being worked out, though.



Jeff's post on the new strategy
Which includes separate book clubs for devs and IT professionals
Posted by wwagner | with no comments
Filed under:
This tidbit came from a discussion with Chris Kinsman about classes that implement IDisposable on the desktop, but not on the Compact Framework

Chris Kinsman wrote about an interesting problem dealing with types that support IDisposable on the desktop, but not on the Compact Framework.

I do have a solution, but it comes with a caveat or two:

using(IDisposable brush = ((object)indicatorBrush) as IDisposable)

{

  Pen indicatorPen = new Pen(stationColor);

  using(IDisposable pen = ((object)indicatorPen) as IDisposable)

  {

    // Draw a path

    g.FillPolygon(indicatorBrush, points);

    g.DrawPolygon(indicatorPen, points);

  }

}

This works on the desktop, with the familiar using statement we all know. On the .NET CF, it becomes using ( null ) which is harmless.

The caveat is when a class that has a Close() method implements IDisposable on the desktop, but not on the CF. Then, you must call Close(). Otherwise, you leak resources on the .NET CF.



Chris's Original Question
Includes the code with #define
Posted by wwagner | with no comments
Filed under:
Is there one language that has better performance than all the rest?

Josh Holmes and I had an interesting discussion about this email he received:

I get a subscription to MSDN Magazine as a part of the MSDN Universal Subscription and the magazine comes before the articles are available on the WebSite. Check out Page 58 of the January issue (Dec 14, 2004).

The program manager for the Visual C++ team states in paragraph 2 the

following:

Another common misconception is that the same kind of superior performance on the .NETFramework can be attained regardless of the language you use -- that the Microsoft intermediate language (MSIL) from various compilers is inherently equal.

Now isn't that special! :-)

He references this article in MSDN magazine: http://msdn.microsoft.com/msdnmag/issues/05/01/COptimizations/default.aspx

Well, his comments are true, but very misleading. He implies that C++ will generate before performing IL than other languages. That’s certainly not accurate. By using the best constructs in each language, you will get high-performing IL. If two different languages generate the same IL, they will exhibit the same performance characteristics. However, if you pick different constructs, regardless of the high-level language, you’ll get different IL, and therefore different performance characteristics.

This article does correctly point out that Managed C++ has some inherent advantages when working on systems that make use of both managed and unmanaged memory, or managed and unmanaged code. Other than that narrow statement, I’m convinced that you can write high-performing .NET code in any language with the proper compiler optimizations, and the right high-level language constructs.



Posted by wwagner | with no comments
Filed under:
Microsoft Researchers are working on an AI engine for Go!

Go is an ancient game (at least 2500 years old, and possibly 4000) most likely originating in China. It looks very simple, but after playing it for a while, or you quickly realize it’s far more complex than chess. Because of that, it’s one of the great AI challenges today. (Current computer Go programs rarely beat amateurs. And, the Deep Blue program that beat Kasparov could take 1.5 years for one move in Go. A different algorithm is needed.)

This link gives a brief overview of the strategy the Microsoft Research is using for an AI engine for Go. It has implications for many different applications, such as computer vision.



The MS Research Link
What a way to Go
Posted by wwagner | with no comments
Filed under:
Chris came and spoke at our user group last night. It was a fantastic presentation.

The Great Lakes Area .NET User Group enjoyed a fantastic talk by Chris Kinsman last night.

He spoke about the challenges facing team development (whether in .NET or any other environment, for that matter). He discussed best practices for Source Control Systems, Nightly Builds, Unit Tests, Smoke Tests, and release planning.

He closed with an overview of how Visual Studio Team Systems handles these challenges in the upcoming Visual Studio Release.



Chris Kinsman's blog
Learn more about his thoughts here.
The Great Lakes Area .NET User Group
Our user group (Chris's slides will appear here)
Posted by wwagner | with no comments
The best tool (IMHO) for delivering database installations

I received this question via email recently:

"I have developed an application using VB.net and SQL.
I have to create the setup file so that I can install this application on another system
 
Forgive me I am a naive programmer, but when I tried to do this using setup wizard, the database won't work.
Although it was running on my system but it is not running on other systems.
 
Kindly advise."

Earlier this fall, I wrote a whitepaper for Wise Solutions on almost exactly this subject.  The only difference is that this paper was geared for ASP.NET applications.  One of the best features in this application, for you, is it's ability to create and install databases on the target machine.  You should check it out, using the links below.



The Wise Installer homepage
The home page for the Wise Installer
The Whitepaper
How to Seamlessly deploy ASP.NET Applications using the Wise Installer
Download the evaluation
Direct link to the evaluation version
Posted by wwagner | with no comments
Filed under:
Always close files and streams

Question:

I read your article Manage C# Objects in Visual Studio magazine.

I'm having a problem using the XmlDataDocument class and was wondering if you think this is a situation where I should use IDisposable as described in your article.  The way the form works is the user will make changes and then click a "Save" button, or other events will trigger a save, which should persist changes to the XML file.

Thanks in advance for your help.

class frmMain : System.Windows.Forms.Form
{
  //code omitted

  string xmlSchema = (@"C:\Projects.xsd");
  string xmlFile = (@"C:\Projects.xml");
  XmlDataDocument xdd = new XmlDataDocument();

  public frmMain()
  {
    InitializeComponent();
    xdd.DataSet.ReadXmlSchema(xmlSchema);
    // load xml data
    XmlTextReader xrd = new XmlTextReader(xmlFile);
    xrd.MoveToContent();
    xdd.Load(xrd);
  }
 
 private void btnAddCfg_Click(object sender, System.EventArgs e)
 {                
   DataTable cfgTbl = xdd.DataSet.Tables["Configuration"];
   DataRow newCfg = cfgTbl.NewRow();
   newCfg["ConfigName"] = "NewConfiguration";
   cfgTbl.Rows.Add(newCfg);
   xdd.Save(xmlFile); // ç Error here: "The process cannot access the
   // file "C:\Projects.xml" because it is being used by
   // another process."
 }
}

Answer: Well, the answer is rather simple:  You never closed the file. When the constructor exits, the XmlTextReader is garbage. Eventually, the .NET Garbage Collector will reclaim that memory.  However, before the GC can reclaim the memory, it will call the finalizer for the XmlTextReader.  That will close the file.  If you wait long enough, the file does get closed.  Long enough is a non-deterministic amount of time.

To fix the problem, you need to explicitly close the file.  You also need to make sure that you close the file, even if an exception gets thrown in your constructor.  That means a using clause, or a finally clause. Your constructor should look like this:

public frmMain()
{
  InitializeComponent();
  xdd.DataSet.ReadXmlSchema(xmlSchema);
  // load xml data
  XmlTextReader xrd = null;
  try {
    xrd = new XmlTextReader(xmlFile);
    xrd.MoveToContent();
    xdd.Load(xrd);
  } finally
  {
    if ( xrd != null )
      xrd.Close( );
  }
}

You can’t put the XmlTextReader in a using clause, because it does not support IDisposable, even though it has a Close() method.

Changing it in this manner ensures that the file is always closed before the constructor exits.  That’s all there is to it.

I hope that helps.  Follow the link below for much more on disposing and closing objects (from my new book, Effective C#)



Implement the Standard Dispose Idiom
Not exactly what he's seeking, but close
The original aticle
The article referenced in the question
Posted by wwagner | with no comments
Filed under: ,
Patrick Steele gave this talk earlier at the Detroit User Group: COM Interop

Patrick Steele, one of our .NET MVP's is a giving a great talk at the Lansing .NET User Group. Here's the abstract:

Start enhancing your COM applications by developing new functionality in .NET! The situation is that you have an existing COM based application that is in production and working, but it needs new features. The choice is, throw it away and start over in .NET or enhance it with more COM code. You don't have time to throw it away and you don't have the will to continue writing legacy COM code. In this session, Patrick Steele will explain the details of COM interop and how .NET exposes it's functionality to COM. Learn how to use interfaces and attributes for hassle-free COM interop with your existing VB6 code.

If you did not see his talk in Detroit, you should make a point to attend this talk.



Patrick Steele's blog
Good tips here
GlugNet
The Lansing .NET User Group Home
Posted by wwagner | with no comments
This one asks how to handle Properties of embedded objects.

Question:

Bill, 

After reading your paper on Visual Studio Magazine, I spent a few hours trying to bind to a subproperty and... I'm wondering if it is possible!

I first coded a ContactList class, a collection of Contact. ContactList is setup as your AddressList so I can use it as a component and bind my UI to it. Nice!

I then added an Addresses property - of type AddressList - to the Contact class. This enabled me to select contactList1 as DataSource and contactList1.Addresses as DataMember in the properties box for a DataGrid. Very nice!

Then I added a Phone property to the Contact class. Phone has type PhoneNumber, a custom class with 2 properties AreaCode and Number. My goal was to use the properties box to bind the Text property of a TextBox control (WinForms) to contactList1.PhoneNumber.AreaCode (in section Data/DataBindings/text of the properties box). But I missed something. I can't managed to have the PhoneNumber property to "expand" in the properties box. I've tried to use differents attributes for AreaCode and Phone properties. I also searched for an interface similar to ITypedList or IListSource, but for a single instance, not a list.

Do you have any idea on how to do it?

Anyway, thank you for the great value paper!

Answer:

Like almost everything, there is more than one answer. The simple answer is that you can modify your Contact class to contain properties for the phone number fields: AreaCode and PhoneNumber. These would simply delegate the work to the contained Phone object.

The other answer might be more elegant, but it is quite a bit more work. The Contact class must support the ICustomTypeDescriptor interface. The key method for your example is ICustomTypeDescriptor.GetProperties(). This method returns a collection of PropertyDescriptor objects, or objects of a class that derives from PropertyDescriptor. A PropertyDescriptor contains information on the name of the property, and can access the property’s Get and Set methods. In your example the name would be something like “PhoneAreaCode”, or “PhoneNumber”. The PropertyDescriptor’s “GetValue” method returns the value of the Phone objects Number property, by going through the Contact and Phone objects. There is a similar “SetValue” property, that sets the value of a named property by going through the Contact and Phone objects.

Incidentally, DataRowView supports the ICustomTypeDescriptor interface to provide the support for named columns in a typed dataset. That implementation uses reflection to determine what columns and relationships are available on a particular dataset. Those are exposed through the designer. At runtime, the same implementation handles the get and set methods for columns in each DataTable. Otherwise, the databinding libraries would not work with indexers, as used to access individual cells in the DataSet.



The original referenced article
Published June 2003 on Fawcette.com
Posted by wwagner | with no comments
Filed under: ,
A few questions and some answers about how to best perform data binding when you create windows forms.

Question: (or actually a few questions. Answers are inline)

I'm an up-and-coming .net developer whose trying to implement databinding to business objects. Your article here has been invaluable. It's the shortest, sweetest, thing I've found to get me up to speed. And I'm happy to say I've got a lot of things working. There's two questions I was hoping you could answer for me though, if you have a moment.

Other than precluding non-serialized events (thanks to Lhotka for pointing this out to me) is there any reason not to use VB.net versus C#? My company prefers VB so that's the route I need to go, unless there's a reason I shouldn't.

Answer: No, there really isn’t much difference. In fact, my favorite resource for Windows DataBinding is Chris Sell’s book. It’s available in both VB.NET and C# versions.

Is it just me, or is databinding to multiple controls finicky? I find your sample (linked above) works fine with just a datagrid. And I am usually able to add textboxes also, binding to the same collection at the same time. But it seems to blow up sometimes. I'm not exactly sure what causes it. But I thought maybe off the top of your head, you would know if this should even work at all?

Answer: Once again, Chris Sells discusses this. The key is that you must have the same datasource for all the controls. If you do that correctly, the CurrencyManager will keep the different controls in synch. However, if you have different datasources, you get different Binding Managers. Different Binding Managers means different binding contexts, which means that the different controls do not stay in synch when the Current index changes. My suggestion is to look at your code and make sure you use the same object for the DataSource in all cases. The DataMember is what you change to get different properties in each different control.



The original article
A discussion of databinding and multiple controls
Chris Sell's book
The C# Version
Chris Sell's book
The VB.NET Version
Rockford Lhotka's blog
Another great resource
Posted by wwagner | with no comments
Filed under: ,
And, thankfully, it's not that hard

The standard Windows application uses the "battleship grey" motif, and square windows. 

You can differentiate yourself using more sophisticated techniques:  Outlook (and almost every RSS aggregator) use popup-windows and notification icons to alert users when important (or not so important) events happen. 

Media Player moves away from the standard shape and color with a variety of custom skins. 

While not every application can get improvement from these techniques, the Windows Forms library & GDI+ already make it reasonably easy.  The November issues of Visual Studio Magazine has an excellent article by Andrew Flick and Jason Beres (Jason spoke at our local user group last Summer, thanks for a wornderful presentation!) that demonstrate the techniques I mention above (and more). It's well worth the read, and it will give you some ideas about how to incorporate these techniques in your own applications. 



Spice up your Windows Forms
An excellent tutorial on using these features

Posted by wwagner | with no comments
Filed under: