I'm trying to create a windows form application that will convert units of measurements from one to the other. My form features navigation buttons that I figured would make it user friendly.
When the user selects a category from the main menu it fills the category of measurement combobox and sets default unit of measurements into two other combo boxes.
These comboboxes allow the user to select which unit of measurement they want. When they choose a category such as distance, it fills the initial and resulting unit of measurement comboboxes.
I therefore have already created a few string[]
that contains each unit of measurement.
string[] distanceUnits = { "Inches", "Feet", "Centimeters", "Meters", "Kilometers", "Miles" };
string[] massUnits = { "Grams", "Kilograms", "Pounds", "Ounces" };
I also created a couple different decimal[]
arrays filled with conversion factors that I have been looking up and editing for precision purposes since I will be doing unit testing. I'd like to easily be able to change the conversion factor or add new ones into the arrays.
For example,
decimal[] massConversionFactors =
{
.001m, // [0] Grams to KiloGrams
.00220462m, // [1] Grams to Pounds
.035274m, // [2] Grams to Ounces
1000, // [3] KiloGrams to Grams
2.20462m, // [4] KiloGrams to Pounds
35.274m, // [5] KiloGrams to Ounces
453.592m, // [6] Pounds to Grams
.453592m, // [7] Pounds to Kilograms
16 // [8] Pounds to Ounces
};
and
decimal[] distanceConversionFactors =
{
.083333m, // [0] Inches to Feet
2.54m, // [1] Inches to Centimeters
.0254m, // [2] Inches to Meters
.0000254m, // [3] Inches to Kilometers
.0000157828282828m, // [4] Inches to Miles
12, // [5] Feet to Inches
30.48m, // [6] Feet to Centimetes
.3048m, // [7] Feet to Meters
.0003048m, // [8] Feet to Kilometers
.000189394m, // [9] Feet to Miles
.3937009133858m, // [10] Centimeters to Inches
.03280840944882m, // [11] Centimeters to Feet
.01m, // [12] Centimeters to Meters
.00001m, // [13] Centimeters to Kilometers
.0000062137m, // [14] Centimeters to Miles
39.3701m, // [15] Meters to Inches
3.28084m, // [16] Meters to Feet
100, // [17] Meters to Centimeters
.001m, // [18] Meters to Kilometers
.000621371m, // [19] Meters to Miles
39370.1m, // [20] Kilometers to Inches
3280.84m, // [21] Kilometers to Feet
100000, // [22] Kilometers to Centimeters
1000, // [23] Kilometers to Meters
.621371m, // [24] Kilometers to Miles
63360, // [25] Miles to Inches
5280, // [26] Miles to Feet
160934, // [27] Miles to Centimeters
1609.34m, // [28] Miles to Meters
1.60934m // [29] Miles to Kilometers
};
That way when the submission button is pressed I can do a calculation such as:
private void ConvertSubmissionButton_Click(object sender, EventArgs e)
{
//User's input value
decimal input = decimal.Parse(UserInputTextBox.Text);
string initialUnits = InitialUnitsComboBox.SelectedItem.ToString();
string resultingUnits = ResultingUnitsComboBox.SelectedItem.ToString();
//conversion of user input to result accepting initial and resulting
decimal result = input * ObjectWithTooManyMethods(initalUnits, resultingUnits);
ResultingValueLabel.Text = (initialUnits);
ResultingValueLabel.Show();
}
This works fine for now, but as I add more methods to the object I wonder if there is a way to consolidate the already created arrays.
The problem I'm having is that I am forced to hardcode every permutation of conversion in the
ObjectWithTooManyMethods(string, string);
What I'd really like to do is create a recursive loop that will go through the distanceUnits[]
massUnits[]
and other unit of measurement category arrays, and creates every possible permutation based on the category's appropriate conversionFactor arrays.
This way I can add on units of measurements and their conversion factors without coding an entire new method in the future.
Is this possible?
This ideal loop would create a single datatype that contains this information and be able to retrieve the decimal value for the conversion factor for initial, and resulting units when the user clicks a submission button.
Such as:
DesiredDatatype<string,string,decimal> conversionFactors = new DesiredDatatype<string,string,decimal>()
{
{initialUnits, resultingUnits, conversionFactor}
};
private void ConvertSubmissionButton_Click(object sender, EventArgs e)
{
//User's input value
decimal input = decimal.Parse(UserInputTextBox.Text);
string initialUnits = InitialUnitsComboBox.SelectedItem.ToString();
string resultingUnits = ResultingUnitsComboBox.SelectedItem.ToString();
decimal result = input * conversionFactors.get(initialUnits, resultingUnits);
ResultingValueLabel.Text = (result);
ResultingValueLabel.Show();
}
Maybe I'm approaching this the wrong way, and/or have been coding too long today.. I have looked up information about tuples and dictionarys and they seem like they would ideal for this scenario but I have failed in creating a working datatype from looping through the information in these existing arrays.
Any advice is greatly appreciated. Thanks a lot!
Since you don't want to use objects, what about using enumerations and dictionaries? You can define an enumeration like this...
public enum MassUnit
{
Grams,
Kilograms,
Ounces,
Pounds
}
To convert enum values to and from strings you can...
var stringArrayOfEnumNames = Enum.GetNames(typeof(Mass));
var enumFromString = Enum.Parse(typeof(MassUnit), "Ounces");
Next you could use a dictionary for your conversion amounts. There's no need to have every combination of conversions, just convert to a standard unit (grams) then convert to the destination unit. This dictionary stores values to convert any mass unit to grams.
public static Dictionary<MassUnit, decimal> MassToGramsMap = new Dictionary<MassUnit, decimal>
{
[MassUnit.Grams] = 1m,
[MassUnit.Kilograms] = .001m,
[MassUnit.Ounces] = .035274m,
[MassUnit.Pounds] = .00220462m
};
Then a conversion would look like...
var value = 100m;
var from = MassUnit.Pounds;
var to = MassUnit.Kilograms;
var convertedValue = value / MassToGramsMap[from] * MassToGramsMap[to];
Now if you wanted to add a new mass unit, you would add it to the MassUnit
enumeration and add its conversion to MassToGramsMap
dictionary and you're done.