Random comments about Sytem.Convert class

The System.Convert class is a neat little class in the BCL (mscorlib) for converting between types. 

vs. IConvertible:
The Convert class is tightly coupled with the IConvertible interface. Convert.ChangeType is just a convenience method to delegate to the IConvertible interface. You can verify this by:
– via looking at the IL in reflector
– trying it out.

If in your code, you need to write a giant switch case to convert your class to a primitive type (int, char, float, double, etc); consider implementing IConvertible.

vs. TypeConverters:
The FX also lets you define custom TypeConverters. These are very separate from the Convert class. Convert.ChangeType will not lookup custom TypeConverters to use in the conversion. You can infer that Convert.ChangeType doesn’t use TypeConverters because of layering. The Convert class is defined in mscorlib.dll; whereas TypeConverter is defined in System.dll. Since mscorlib has no dependencies; it can’t use classes defined in other dlls. You can also determine the separation with Reflector or experimentation.

MSDN has more on the comparison between TypeConverters and IConvertible.

vs. Casts:
A lot of the Convert class just exposes numerical casting operations via a function call interface.  So instead of:

float f = …
int i = (int) f;

you can say:

float f = …
int i = Convert.ToInt32(f);

This can be useful in that it provides numerical casting functionality to a language without casting. Given the CLR’s cross-language nature, this can be very relevant. It can be a essential workaround for very primitive .NET languages.

One important caveat is that casting has a lot of policy. For eg: do you truncate or round? Under what conditions are InvalidCastExceptions thrown? etc. The Convert class picks 1 particular policy, and that policy is very different than C#. For example, C# would round 4.5 and 5.5 to 4 and 5 respectively. Convert.ToInt(float) would round them to 4  and 6 respectively. Or in table form:

float C#’s (int) cast Convert.ToInt(float)
4.1 4 4
4.5 4 4
5.5 5 6

Bonus points to anybody who can see the pattern for Convert.ToInt(float) without having to check MSDN.

Comments (7)

  1. dd says:

    round to even?

  2. Andrew says:

    My guess: Convert.ToInt implements ‘Round to Even’ (aka. Banker Rounding), whereas C#’s int cast does ‘Nearest Rounding)…

  3. slywitherspoon@hotmail.com says:

    Banker’s rounding?

  4. Tim Dawson says:

    C# will truncate – round is the wrong word to use. Casting 4.9 to an int would still result in 4.

  5. Peter Ritchie says:

    I’m not a big fan of Convert, mostly because it has numerous methods that are documented as "always throws": Convert.ToDecimal(DateTime), Convert.ToDouble(DateTime), Convert.ToInt16(DateTime), Convert.ToInt64(DateTime), Convert.ToSByte (DateTime), Convert.ToSingle(DateTime), Convert.ToUInt16(DateTime), Convert.ToUInt32(DateTime), Convert.ToUInt64(DateTime), Convert.ToChar (DateTime), Convert.ToByte(DateTime), and Convert.ToBoolean(DateTime).  I’m assuming they exist for symmetry or backward compatibility (although, I fail to the logic).

    While writing code, you’re not going to remember that a subset of methods in a pattern of methods "always" throws. The compiler doesn’t stop you from writing the code because those methods exist.  Their existence cause the compiler to assume they function in at lease one scenario.

  6. jonnybgood says:

    It’s much easier to search for a Convert than a cast since a cast just looks like an expression.

  7. Pop Catalin says:

    Convert uses Intel IEE…something for converting floating point numbers to integers and wich means numbers get rounded to the nearest even value.

    C# cast to int is a truncate actualy, not a rounding.