Tuesday, December 14, 2010

When is String.Empty != String.Empty?

[Note: This post is based upon an old blog post that I'm migrating for reference purposes, so some of the content might be a bit out of date. Still, hopefully it might help someone sometime...]
Have just spent the last few days at a client site investigating a particularly obscure issue...

We've been working with a third-party API developed in .NET 1.1. A while ago, some ASMX services were built on top of the API, in VS2003 / ASP.NET 1.1. We wanted to upgrade these to VS2008, and eventually to WCF instead of ASMX.

So, I ran the upgrade on my development machine, everything upgraded fine, the services were functional, and I could successfully call the .NET 1.1 API. I deployed the services to an integration web server, and they stopped working with an obscure custom API error. I then spent a day reverse engineering the relevant bits of the API out into plain code using Reflector and the FileGenerator add-in (once again, yay for Reflector!), only to discover that the issue was with the following lines of code:

Private _OpenTags As String = ""
'...
If Not _OpenTags Is String.Empty Then
  '...

When the value of _OpenTags was "", the If test was returning False on my development machine (expected), True on the integration web server (unexpected).

OK... so after investigating potential differences in Framework configuration (eg, does Culture make a difference to how empty strings are evaluated?), and OS (development = WinXP, integration = Win2k3), I abandoned those paths and investigated the Framework versions on each machine.

Development machine had .NET 1.1, .NET 2.0 SP2, .NET 3.0 SP2, and .NET 3.5 SP1.

Integration machine had .NET 1.1, .NET 2.0 SP1, .NET 3.0 SP1, .NET 3.5 (no SP1).

OK... so, check out the list of fixes in .NET 3.5 SP1 (which also happens to include .NET 2.0 SP2 and .NET 3.0 SP2). Nothing there...

So, I built a test Win2k3 server, installed the same framework versions as the integration server, and ran my test... Sure enough, _OpenTags wasn't "equal to" (at least in a reference sense...) String.Empty, even when it was set to "". Installed .NET 3.5 SP1, and re-ran the test... Success: _OpenTags was String.Empty when set to "".

Eventually, to justify my desire to install .NET 3.5 SP1 on the integration server, I found the following in the .NET Framework 3.5 documentation:

http://msdn.microsoft.com/en-us/library/system.string.intern.aspx

The relevant part is the "Version Considerations" section, particularly the following statement:

In the .NET Framework version 3.5 Service Pack 1, the Intern method reverts to its behavior in the .NET Framework version 1.0 and .NET Framework version 1.1 with regard to interning the empty string.

... (example)

In the .NET Framework 1.0, .NET Framework 1.1, and .NET Framework 3.5 SP1, str1 and str2 are equal. In the .NET Framework version 2.0 Service Pack 1 and .NET Framework version 3.0, str1 and str2 are not equal.

Hmm... that would explain it... Thanks Microsoft. I haven't been able to find this listed in the "Breaking Changes" for .NET 2.0, maybe because it's so obscure, or just slipped their minds...

Note that it also depends on the way that you compare your string to String.Empty... In my case, as I was working with a third-party API, I didn't have any control over that...

Thanks for listening...

No comments:

Post a Comment