Anyone who has worked with Visual Basic for any length of time should be familiar with the VB Type Conversion Functions like CBool, CInt, and CStr. These functions can provide a short and easy way to coerce the value of one type into another. I’ve been working with ~300,000 line VB .NET project for the past couple of years that is littered with calls to these functions. We never had any issues with them until we sat down to convert the project to C#.
Converting a 300,000 line project from VB .NET to C# is a pretty big undertaking and I plan on putting together a post-mortem at some point in the future, but I wanted to briefly outline one subtle issue we hit with the CStr function and enumerations.
Consider the following enumeration (declared in C#):
1 public enum ReviewStatus
3 NotStarted = 0,
Let’s say you want to use this enumeration in the query string of a web page that displays a report. In VB .NET you could easily use the CStr function to take an instance of the ReviewStatus enumeration and convert it to a string:
1 Dim selectedStatus As ReviewStatus = GetSelectedReviewStatus()
2 Request.QueryString.Add("reviewStatus", CStr(selectedReviewStatus))
This results in a URL that looks like:
When provided with a Numeric Data Type the CStr function will return a string representing the number. The use of CStr here makes me a bit nervous because it doesn’t provide any means of specifying an IFormatInfo, but if globalization isn’t a concern using CStr here is probably “good enough”.
When we set out to convert our project to C# we found dozens of places where we were using CStr to convert an enumeration into a string. Because there is no direct equivalent of CStr in C#, we opted to use ToString instead. The VB .NET code above turned into:
1 var selectedStatus = GetSelectedReviewStatus();
2 Request.Querystring.Add("reviewStatus", selectedStatus.ToString());
At first we didn’t see any issues with this conversion until we started testing the application. We soon discovered that the URL in the converted C# project looked like this:
The code that consumes the ‘reviewStatus’ query string variable was expecting an integer that could be cast to the appropriate enumeration member was was throwing exceptions trying to parse the ‘InProgress’ value.
To resolve this issue, we ended up having to first cast the enumeration value to an integer and then calling ToString on the newly cast integer.
But What About Convert.ToString ?
If you search Google for the phrase, “CStr equivalent in C#” you’re likely to find forum posts indicating that Convert.ToString should be used in place of CStr. Convert.ToString might be an appropriate substitute for CStr in many instances, but using Convert.ToString on an enumeration in C# will yield the same result as .ToString’ing the enumeration value, and therefore didn’t help with our problem.