An Old Problem is New Again

I ran into a problem yesterday that brought back memories. And not the good kind of memories either.

I'm doing some work using TypeConverters. In particular, I'm creating a Windows Forms control that functions in a manner similar to a PropertyGrid, but with a user interface that looks more like a typical Windows form. You know, with labels, and text boxes. Because this is a generic control (that is, the fields which get displayed depends on the object associated with the control), I'm doing a lot of reflection to retrieve the properties that are required. And I'm using reflection (the GetValue/SetValue) to interact with the object. This last part (the SetValue method in particular) means that I'm using type converters to move the string values that are in the text boxes into the actual properties themselves.

Now type converters are quite useful. They expose a ConvertFromString method that (not surprisingly) takes a string value and converts it to a value of the associated type. If the string is not valid for the destination type, an exception is thrown.

Problem 1: the raised exception is System.Exception. I have no idea why the exception surfaced from ConvertFromString is an Exception. The InnerException is a FormatException, which is the type of exception that I would have expected. But no, ConvertFromString throws Exception. This forces me to use a pattern that I loathe - try {...} catch (Exception) { }

Whenever I teach, I always harp on this. You should (almost) never catch the general Exception object. You should only catch specific Exceptions. But because of ConvertFromString, I have to add to my list of cases where catch (Exception) is required.

But why should this matter, you ask. TypeConverters exposes an IsValid method. You should be able to check for the validity of the string value prior to calling ConvertFromString. This would completely eliminate the need to catch any exceptions at all. And it's the best practice/recommended/ideal way to go.

Problem 2: Int32Converter.IsValid("bad") returns true.

Think about that last one for a second.

According to the type converter for Int32, the string 'bad' is a valid integer value. In my world, not so much. If you spelunk the various classes in .NET Framework, you find out that IsValid is supposed to be overridden in the various converter classes. But the numeric classes don't bother to do so. As a result, the IsValid that actually services my request just returns a true regardless of whether the string is valid or not.

What's worse, this is a known bug that will never be resolved. Apparently to make IsValid work for Int32Converter is considered a breaking change.

So my suggestion (courtesy of Dave Lloyd) is to add a new method to the TypeConverters. Call it IsReallyValid. IsReallyValid could then be implemented properly without the breaking change. It could take the CultureInfo object necessary to truly determine whether a string is valid. For the base type converter, it could simply return a true.

Heck, let's go a step further and mark IsValid as being Obsolete. That would force people to move to IsReallyValid and correct any problems in their applications. And maybe, in a couple of versions, Microsoft could reintroduce a working version of IsValid and mark IsReallyValid as being obsolete. In this way, four versions from now (that's about 10 developer years), IsValid will work the way it's supposed to (and everyone would expect it to).