Convert and Math classes aren’t smell. It’s tasty!
Few days ago I started to follow Iris Classon(@IrisClasson) on the Twitter. She is asking on her blog (usually) everyday one question about coding, design, best practice e.g. in the 365 Stupid Questions.
These questions are really practical, because they makes me think about and search the answers. Reading the comments below the question is also valuable and give me different views at some problem. Literally it push me forward and I am happy for that.
Converting answer into an article
While I was reading comments under the Stupid Question 43: Are utility, helper and or static classes and methods considered a code smell? I notified one respectively part of one, that really don’t fit my opinion and I start to investigate more about Convert class. Joep Beusenberg wrote:
Unlike the previous replies I think Convert and Math are two of the worst constructed utility classes in existence.
IMHO Convert and Math have no reason to exist whatsoever. All of the Convert methods could easily be added as methods to existing types. (Convert.ToInt32(object o) could have been int.From(object o), and Math.Sin(double n) could just have been n.Sin(), perhaps even as the property n.Sin, since it’s quite pure.)
Same goes for the Array class.
I just miss the point why are System.Convert and System.Math classes bad. Each of both has its own responsibility. One for converting between built-in framework types and second for mathematical operations with numbers. I was thinking about it for some time, but I don’t get why these are the worst constructed utility classes. I still feel these two classes exactly follows the Single Responsibility Principle. Object can’t convert itself to another and object can’t compute itself to a result(this is direct dependency between objects and that’s bad). There needs to be responsible object for that work. So, there are Convert and Math classes for it. Moving these methods to an object is not good practice.
As Joep wrote int.From(object o). Is it possible to convert to int from (imagine your custom) object without knowing how to do that? I don’t think so. Take a look at these built-in framework types
As you can see all of these types are types we are using daily while coding. Except last three are all structures. Structures are recommended to use as primitive types not exceeding 16 bytes. In other words structures best fits data chunks only. Is responsibility of any data object(class or structure) to provide methods to do something with itself? I thing data containers must have only the minimum needed to work with them. Nothing more. So, it is really good there are Convert and Math class to do the work.
There is even more, don’t you know?
Each of types in the list above explicitly implements IConvertible interface and its methods listed below
This explicit interface implementation you can simply use whenever you don’t want to use static Convert class together with base types.
Methods in Convert class usually box passed value to IConvertible type and calls suitable method or directly returns the value or throws an exception. Convert class only encapsulates working with IConvertible interface and its methods we can call directly from our code if we want. Why we want to do when Convert class handles all checks for nulls and overflows? And better. Convert class can be easily extended to convert custom class to base types. We only need to explicitly implement that interface.
Take a look at GitHub repository Object.Conversion where you’ll find some example usage of IConvertible directly and explicitly implemented in Point structure.
I really think that Convert and Math classes are good and aren’t code smells. I am always trying to keep away of utility classes, cause there is way of doing it better without them, but sometimes when application gets too complex it is better to separate same/similiar behavior of more classes to one utility class. It is better to have one class responsible for some area of functionality over more types and when you do it extensible it is your win.