0

I was wondering if i could get a hand please. Can someone explain to me why my string sqrt is unassigned in the finally block? Why do I have to declare it? Why can't it be declared in the try or catch statement? It would make coding less tedious and more organized.

    private void btnDisplay_Click(object sender, EventArgs e)
    {
        int number;

        string sqrt;

        try
        {

            number = Convert.ToInt32(tbInput.Text);
            //Why cant i just have it as "number=COnvert.ToDouble(tbInput.Text)?//
            Convert.ToDouble(number);
            if (number < 0)
            {
                throw new NegativeNumberException();
            }
            sqrt = Math.Sqrt(number).ToString();


        }
        catch (FormatException error)
        {
            lbOutput.Items.Add(error.Message);
            lbOutput.Items.Add("The input should be a number.");
            sqrt = "not able to be calculated";


        }
        catch (NegativeNumberException neg)
        {
            lbOutput.Items.Add(neg.Message);
            sqrt = "not able to be calculated";


        }
        finally
        {
            //Here is where i am having the issue "Unassigned local variable"//
            lbOutput.Items.Add("Square Root " + sqrt);
        }

    }

       class NegativeNumberException : Exception
       {
          public NegativeNumberException()
            : base("Number can’t be negative")
          {

          }



      }
    }
}

What I am attempting to achieve in the finally block is for "Square Root" and "sqrt" to be displayed in the list box no matter what the value of sqrt is. If I output sqrt to the list box in any of the other blocks, it works (because it has been declared). Does anyone know how can I can do this? I bet it's probably something simple too. I don't mean to rant or anything its just I have been up for the last 12 hours so I am begin to feel defeated. I appreciate everyone's help, I truly do.

Daniel
  • 8,794
  • 4
  • 48
  • 71
Spr89
  • 81
  • 1
  • 9
  • http://stackoverflow.com/questions/94977/why-arent-variables-declared-in-try-in-scope-in-catch-or-finally here is your answer :) – Zze Apr 29 '15 at 05:57
  • Declare the variable number as double than you can do this number=Convert.ToDouble(number); – Mairaj Ahmad Apr 29 '15 at 05:57
  • 1
    Well, look at it this way: `finally` is guaranteed to run *always*, no matter what (excluding power failure and such). So what if something in the `catch` blocks goes wrong before `sqrt` is set? Or what if an exception is thrown that you don't catch? Then `sqrt` is not set, in other words "unassigned". So the easiest way to get around that is to initialize it to *something* right away. Like: `string sqrt = string.Empty;` or even `string sqrt = null;`. – Corak Apr 29 '15 at 06:00
  • @Corak, perfect, i initialized the string before any of the blocks and now it carries over. thanks again man for your help. ^_^ – Spr89 Apr 29 '15 at 06:04
  • @Spr89 - there is a slight but important difference. The value assigned to `sqrt` would have always been "carried over", but there were paths in your code that could lead into the `finally` block without ever assigning anything to `sqrt`. So assigning *something* (`null` or `string.Empty` or even `"Hello World"`) right at the beginning guarantees that, well, there *is* something assigned to `sqrt` before the `finally` block runs. – Corak Apr 29 '15 at 06:11

6 Answers6

4

If any of these lines in your code:

number = Convert.ToInt32(tbInput.Text);
//Why cant i just have it as "number=COnvert.ToDouble(tbInput.Text)?//
Convert.ToDouble(number);
if (number < 0)
{
    throw new NegativeNumberException();
}

Throws an exception that is not of type NegativeNumberException or FormatException, then due to this declaration:

string sqrt;

Your sqrt variable remains unassigned.

You can solve this by declaring it like:

string sqrt = null; // or ""

Regarding your comment:

Why cant i just have it as "number=COnvert.ToDouble(tbInput.Text)?

Try this:

var number = Double.Parse(tbInput.Text);
Alex
  • 13,024
  • 33
  • 62
  • ahhhh, didnt know that, so basically there is no way to have the string value carry over? even if it is declared in anyone of the other blocks? – Spr89 Apr 29 '15 at 06:01
  • A different exception than the two you are handling could be thrown and cause `sqrt` to remain uninitialized. – Alex Apr 29 '15 at 06:03
  • @Spr89 - it *will* be "carried over", but your code doesn't guarantee that there will definitely be an assignment before `finally` runs. – Corak Apr 29 '15 at 06:03
2

You can't declare it in try block, because local variables are binded by scope. In short, local variable declared in block, that is {}, has visibility in that block only. To addon, it will better if you initialize sqrt to "" or string.Empty, while declaring it.

Abhishek
  • 6,912
  • 14
  • 59
  • 85
0

Change :

int number;
string sqrt;

Update :

double number = 0.0;
string sqrt = string.Empty;
Krunal Mevada
  • 1,637
  • 1
  • 17
  • 28
  • Why will this answer solve OP's problem? My point being, posting a wall of code as an answer with no explanation as to **why** it is an answer makes a for a useless answer. – Tim Apr 29 '15 at 06:03
  • I have change `double number = 0.0; string sqrt = string.Empty;` try and check it. – Krunal Mevada Apr 29 '15 at 06:05
  • Wasn't my question, and I don't need to try the code to know what it will do. Again, my point is including an explanation of the change and why it will make the code work will make a good answer. Code-only answers don't teach anyone anything. The explanation of the change you made and **WHY** should be in your answer. – Tim Apr 29 '15 at 06:06
0

Try assigning a value on the sqrt. string sqrt = "";//on the declaration sqrt might not contain any value invoking the problem.

0

@Corak, initializing the string before any of the blocks solved the problem.

i changed

     string sqrt;

to

     string sqrt=string.Empty;
Spr89
  • 81
  • 1
  • 9
0

sqrt will only be available in the scope it is declared. A scope is usually delimited by curly braces, such as a method body, for statement, or in this case your try, catch, and finally clauses. You will notice the same issue when trying to declare a variable in an if clause, then try to use that variable in the else counterpart. If you have a lot of these, and are set on declaring it only within the try or catch clauses, one alternative is to create a global map of variables, then assign the "sqrt" key to the object you want within each scope.

Nick
  • 1