0

I'm working on an application that lets the user convert distances to and from inches, feet, and yards. I'm having a bit of a problem with the output. Here's my code:

private void convertButton_Click(object sender, EventArgs e)
{ 
    int fromDistance = 0;
    int toDistance = 0;

    fromDistance = int.Parse(distanceConverterTextBox.Text);
    string distanceInput = fromListBox.Items.ToString();
    string distanceOutput = toListBox.Items.ToString();

    switch (distanceInput)
    {
        case "Inches":
            switch (distanceOutput)
            {
                case "Inches":
                    toDistance = fromDistance;
                    break;

                case "Feet":
                    toDistance = fromDistance / 12;
                    break;

                case "Yards":
                    toDistance = fromDistance / (3 * 12);
                    break;
            }
            break;

        case "Feet":
            switch (distanceOutput)
            {
                case "Inches":
                    toDistance = fromDistance * 12;
                    break;

                case "Feet":
                    toDistance = fromDistance;
                    break;

                case "Yards":
                    toDistance = fromDistance / 3;
                    break;
            }
            break;

        case "Yards":
            switch (distanceOutput)
            {
                case "Inches":
                    toDistance = fromDistance * 3 * 12;
                    break;

                case "Feet":
                    toDistance = fromDistance * 3;
                    break;

                case "Yards":
                    toDistance = fromDistance;
                    break;
            }
            break;

    }
    convertedDistanceLabel.Text = toDistance.ToString();
}

private void exitButton_Click(object sender, EventArgs e)
{
    this.Close();
}

And here's what the app looks like:

Distance Converter application window

My control names if they help:

  • The input TextBox: distanceConverterTextBox
  • The output Label: convertedDistanceLabel

I've even tried not declaring the ints to be 0, then I tried one and/or both, and the output is still zero no matter what. It can really be a simple case of accidentally using the wrong control name, but I really don't know what else to do at this point, so extra eyes will be greatly appreciated.

Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68
  • Set a breakpoint on the function, and step through it (`F10` in VS). You can look at what the values are for your variables. I'm guessing that your issue is with `.Items.ToString()` lines when you're trying to get the values of the controls. I don't think it returns what you're expecting it to return. This link has some information on how to get the values: https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.listbox.items?view=netframework-4.8 – Dortimer Jan 24 '20 at 22:08
  • `fromListBox.Items` and `toListBox.Items` are collections. You probably want the current `SelectedItem` of both. With a ListBox, you usually call `string theItemText = [ListBox].GetItemText([ListBox].SelectdItem)` to retrieve the item selected as text. It also depends on what you put inside those ListBoxes... You should put a breakpoint in `fromDistance = (...)` and inspect the values you get. – Jimi Jan 24 '20 at 22:13
  • 2
    Also remember that integer divided by integer is *integer*. `3 / 12` is not 0.25, because that's not an integer. It's zero. If you intend integer divided by integer to be double or decimal, then do the arithmetic in doubles or decimals. – Eric Lippert Jan 24 '20 at 22:26
  • Also, never use `Parse` for human-provided inputs because humans can provide non-numbers, which will crash. Use `TryParse`, and check the output for correctness. – Eric Lippert Jan 24 '20 at 22:27
  • Your switches all lack a `default`. Add one to each! It will help you find bugs. Something like `default: Debug.Fail("Unexpected value:" + distanceInput); break;` – Eric Lippert Jan 24 '20 at 22:30
  • @EricLippert - In general, when should we throw and log an exception instead of making use of a Debug Fail/Assert? Since in Release the Debug calls will be elided, there could be issues that did not occur during the debugging/testing but that appear in a particular production environment. Isn't it better to have some clear indicator of failure in the production environments too? – Luca Cremonesi Jan 27 '20 at 19:28
  • 1
    @LucaCremonesi: Great question; a comment is not the best place for a long answer. The short answer is: "throw" statements should be *testable*; there should be a way to make a test case demonstrate that the method throws when it should. Debug assertions should be *not testable*. There should never be a way to make a test case assert. **Exceptions tell you about the caller's mistakes. Assertions tell you about the truth.** The purpose of an assertion is to tell the developer when something they believe to be true is actually false. – Eric Lippert Jan 27 '20 at 19:51
  • 1
    @LucaCremonesi: For example, consider a method `void Sort(int[] a)` which sorts an array. `if (a == null) throw ArgumentNullException...` is testable; there is a way you can call the method that causes the exception. But suppose just before the return we have `Debug.Assert(a.Length < 2 || a[0] <= a[1]);` That is, either the array has zero elements, or it has one element, or the sorted array has the first element smaller than the second. That is a **truth** about the sorted array. There should be **no situation whatsoever** in which that assertion is violated, so no test case. – Eric Lippert Jan 27 '20 at 19:56
  • @LucaCremonesi: So in this specific example, if there is a test case which can demonstrate that the inputs or outputs are not as expected, then there should be a throw, and a corresponding unit test which verifies that the throw happens when it should. If there is not, then an assertion tells the developer when they have accidentally violated a program invariant, by, say, adding a new item but not adding the corresponding case. – Eric Lippert Jan 27 '20 at 20:04

1 Answers1

0

The problem is because you are converting all the items to string, you should convert only the selected item to string or in my opinion use their ids

For Selected Item

listBox.SelectedItem.ToString();

for the Selected Index use

listBox.SelectedIndex