I have a similar problem to the post Accessing a static property of a child in a parent method. The preferred answer hints that the design of the classes is faulty and more information is needed to discuss the problem.
Here is the situation I want to discuss with you.
I want to implement some unit aware datatypes like length, mass, current, …
There should be an implicit cast to create the instances from a given string. As example “1.5 m” should give the same as “150 cm”, or “20 in” should be treated correctly.
To be able to convert between different units, I need quantity specific conversion constants.
My idea was to create an abstract base class with some static translation methods.
Those should use class specific statically defined dictionary to do their job.
So have a look at the example.
public class PhysicalQuantities
{
protected static Dictionary<string, double> myConvertableUnits;
public static double getConversionFactorToSI(String baseUnit_in)
{
return myConvertableUnits[baseUnit_in];
}
}
public class Length : PhysicalQuantities
{
protected static Dictionary<string, double> myConvertableUnits = new Dictionary<string, double>()
{
{ "in", 0.0254 }, { "ft", 0.3048 }
};
}
class Program
{
static void Main(string[] args)
{
Length.getConversionFactorToSI("in");
}
}
I think this gives a rather intuitive usage and keeps the code compact and quite readable and extendable. But of course I ran into the same problems the referenced post describes.
Now my question is: How can I avoid this problems by design?
I think this could be solved with generics to still look readable. Refined as per Slaks suggestion to fit the registration into the static constructor to make it thread safe per se.
So if I am not mistaken:
SIConversion<Length>.GetFactor()(1 char more)code needed to implement on derived classes very boilerplate
register(string,double);(actually shorter than your dictionary definition)Output:
1In case you wonder why I made
PhysicalQuantitiesabstract: to avoid using it withSIConversion<PhysicalQuantities>.GetFactor()since we don’t have a conversion for a base class. You probably don’t need instances of a base class like this anyway – it is not a full representation of a quantity, so it will probably contain reusable methods only.Another suggestion would be to use an Enum for the baseUnit instead of a string. Since everybody is striving for type safety and crying foul on magic strings, it probably is a good path to follow :))