1

Let's say I have a function Rotate (float angle). When I call this function, I probably won't remember if this function takes the angle in degrees or radians. For this reason, I call functions like these RotateDegrees (float angle). That's much better, especially, if I call my variables degAngle or radAngle. That way you can see at once if the code is correct without having to look at other places.

But there may be an even better way!

Why don't I just make a different class for every unit? Like

public class Degree
{
    public float value;

    public Degree (float value)  
    {
        this.value = value;
    }
}

and the same for hours, kilometers, mol, lightyears and so on.

That way there would be no ambiguity at all, I just have to make a bunch of overloads for every function, or define conversion operators for each class.

But I never saw code like that. Is it not that useful in practice? Also, the code I'm writing is performance critical, would there be any performance losses?

NounVerber
  • 135
  • 7
  • 2
    Why not use one unit of measurement for everything, that way you wont have to worry about conversion (until you're interacting with the user) and you will minimize inaccuracies due to conversions (rounding, floating point limitations)? – Matthew Feb 21 '13 at 03:12
  • 1
    You should consider what F# offers regarding Units of Measure (http://blogs.msdn.com/b/andrewkennedy/archive/2008/08/29/units-of-measure-in-f-part-one-introducing-units.aspx). I know its a different language, but its syntactically similar. as a c# dev, I found F# to be a small learning curve. – Glenn Ferrie Feb 21 '13 at 03:16
  • More info from MSDN: http://msdn.microsoft.com/en-us/library/dd233243.aspx – Glenn Ferrie Feb 21 '13 at 03:17
  • If you do so, take advantage of operator overloading as well. In fact, I posted an answer about this very concept not too long ago. The implementation isn't perfect, definitely would like to rewrite the whole thing, but it would get you somewhere: http://stackoverflow.com/a/12232002/1269654 – Chris Sinclair Feb 21 '13 at 03:21

2 Answers2

1

It can definitely be a good idea if your program makes frequent use of that particular unit.

You may want to make it a struct instead of a class though.

For example, I like to use a struct for Percent. It improves readability and helps prevent problems with developers getting confused between say 50 or 0.5 to indicate 50%.

As an example, see the Unit structure in the .NET framework which is used to differentiate between pixels, percents and points when dealing with web related sizes.

cbp
  • 25,252
  • 29
  • 125
  • 205
  • 3
    And make sure that struct is NOT MUTABLE! – Jesse C. Slicer Feb 21 '13 at 03:19
  • 1
    I too like the use of a Percent type. Overloading addition so that you can do (e.g.) `value += 10.Percent()` is nice too. :) – porges Feb 21 '13 at 03:56
  • @ Jesse Why is it essential for the struct to be immutable? I still have to learn about immutable types, so I don't know if there is a specific reason in this case or a general one that I'm going to find out anyway. – NounVerber Feb 21 '13 at 05:45
  • 1
    An immutable struct is good for representing things like "9 degrees". Why would the value "9 degrees" be mutable? What would you want to change about "9 degrees"? Nothing - "9 degrees" is always "9 degrees". Notice this is different to a class, which is good for representing something like a customer called "John Smith". All types of things can change about "John Smith" over time - he can get married, grow older, go bankrupt, change his name etc. – cbp Feb 21 '13 at 05:50
  • Hm, I don't quite get it. I don't see what kind of bad thing could happen if I make it mutable. Sry, I know this is off-topic. – NounVerber Feb 21 '13 at 06:01
  • See here: http://stackoverflow.com/questions/4581579/value-objects-in-ddd-why-immutable – cbp Feb 21 '13 at 06:25
  • @NounVerber @cbp nailed it - take the constant `9`. Would you like to be able to say in code `9 = 32` and change the definition of `9` everywhere? Obviously not. Same goes at a fundamental level of these types of structs. An instance of `Percent` which is initialized to 50% should have the value of `.05` for the rest of its meaningful life. I'd hate to use it and have it be changed to 70% somewhere along the way. – Jesse C. Slicer Feb 22 '13 at 19:26
1

I'm not sure about C# but there's a pretty famous article on using C++ templates to enforce units at compile time. I can't find the article but the jist was that any unit could be represented as a product of powers of fundamental measurements. So for example velocity = (length)^1*(time)^-1. So you defined something like

template <int lenPower, int timePower>
class Unit {
  double val;
};

typedef meter Unit<1,0>;
typedef second Unit<0,1>;
typedef velocity Unit<1,-1>;

Then you overload the * and + operators to make sure you can only add compatible units and that multiplication yields a unit with the correct power and you've enforced correct unit manipulation at compile time. Sorry I don't remember more details and can't find the article. Google "template metaprogramming units example" and something will come up. Also sorry I'm talking C++. I know C# supports generics so something similar should be possible.

C. M.
  • 100
  • 1
  • 4
  • In C++ you can use values (e.g. 1) as template parameters, which you can't do with generic parameters in C#. It's not really workable to enable unit-safety at the type level in C# (and I've tried!). It's ok for simple things, but you can't encode things like m*m/s*m = m^3/s. – porges Feb 21 '13 at 03:55