Local variable unassigned issue using Try, catch, finally - c#

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.

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);

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.

Change :
int number;
string sqrt;
Update :
double number = 0.0;
string sqrt = string.Empty;

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

#Corak, initializing the string before any of the blocks solved the problem.
i changed
string sqrt;
to
string sqrt=string.Empty;

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.

Related

can I initialization int variable in unity c#?

I want to try initialization int variable
and I think I can use this code.
result = int.Parse("");
Is it work or error?
First of all int.Parse(someString) could produce an exception if the string couldn't be parsed so if you really need to initialize with the value inside a string the better aproach is:
int result = -1; //or any other value that points to an inizialization error
int.TryParse(someString, out result);
or in one line as #Uwe Keim points:
int result;
if (!int.TryParse(someString, out result)) result = -1;
also you can use the horrible try/catch aproach (if for some weird reason you're binded to Parse instead TryParse):
int result;
try
{
result = int.Parse(someString);
}
catch
{
result = -1; //or any other value that points to an inizialization error
}
Or, of course if someString is a constant value you didn't need all the parse problem:
result = 0;

Local variable and Try/Catch

I get an error, a red line below the variable intAge in the if-statement in the code. It says the variable is local, but how could it be local when it is declared in the beginning of the code? Does it have to do with the Try/Catch part? The reason why my code looks like it does, is just beacuse I have to use a Try/Catch in the code for this task. Preciate some suggestions to solve this in a similiar and correct way? Thanks!
int intAge;
try
{
intAge = int.Parse(age);
}
catch (Exception)
{
MessageBox.Show("Enter an age in numbers!","Error!");
}
finally
{
}
// Check input
if (intAge < 1)
{
inputOk = false;
errorMessage = "Please enter 1 or higher!";
}
just initialize the intAge:
int intAge = 0;
You are getting error use of unassigned local variable.
Since you are assigning the value in the try block, the compiler can't determine if the assignment will take place or not (in case if int.Parse(age) throws an exception), and then in your check if(intAge<1) you are getting the error because you are using a variable not previously assigned.
Definite assignment - MSDN
At a given location in the executable code of a function member, a
variable is said to be definitely assigned if the compiler can prove,
by static flow analysis, that the variable has been automatically
initialized or has been the target of at least one assignment.
If int.Parse fails, the intAge variable will not be initialized.
You may initialize it at delecration
int intAge = 0;
You may avoid the double error :
int intAge;
if (!int.TryParse(age, out intAge))
{
inputOk = false;
errorMessage = "Enter an age in numbers!";
}
else
{
// Check input
if (intAge < 1)
{
inputOk = false;
errorMessage = "Please enter 1 or higher!";
}
}
It's local because it's declared in the local scope. Your code may be better structured like:
int intAge;
if (!int.TryParse(age, out intAge))
{
MessageBox.Show(...
}
else
{
if (intAge < 1)
{
inputOk = false;
errorMessage = "Please enter 1 or higher!";
}
}
With your code above you will display two errors, one for non-numeric, and then one for less than 1. The initial complaint of the compiler was because your integer was not guaranteed to be initialised.
The compiler complains that the local variable intAge might not have been initialized when used for the first time. This may happen when int.Parse(age) throws an exception. To correct this, just initialize intAge to some proper value.
The problem is age is not initialized initialize it to 0 , and try . it must work

If statement can't change local variable

Why can't i change value with an if statement?
int amount;
string inputbalk = inputbar.Text;
if (inputbalk== string.Empty)
{
amount = Convert.ToInt32(inputbalk);
amount = 1;
}
if (inputbalk != string.Empty)
{
amount = Convert.ToInt32(inputbalk);
amount = 1;
}
int onepercent = amount/= 100;
It will see "amount" as an unassigned variable, even though I set it to 1, by two different if-statements.
If I debug, I get this:
"Error 1 Use of unassigned local variable 'amount'"
Thanks for help guys, It is fixed/solved.
Just change second if to else
if (inputbalk== string.Empty)
{
amount = Convert.ToInt32(inputbalk);
amount = 1;
}
else
{
amount = Convert.ToInt32(inputbalk);
amount = 1;
}
The compiler can't make sure that one of two if statements will work anyway, so it will throw error that your variable amount can be unassigned.
In if/else notation one of two code blocks will be done anyway, so compiler will not throw error and everything will work as you want.
There is chance of having inputbalk as null :)
if is not a loop
considering inputbalk is string, it can be a null, you don't check for it, so could happen that it's your case.
Change your code, like this:
if (string.IsNullOrEmpty(inputbalk))
{
amount = Convert.ToInt32(inputbalk);
amount = 1;
}
else
{
amount = Convert.ToInt32(inputbalk);
amount = 1;
}
Hope this helps.
The problem is that the compiler cannot see that amount is definitely assigned. You know that inputBalk can't change between the first and second time it is evaluated, and that exactly one of the if conditions will be true, but the compiler doesn't check this. It sees only that there is a path where amount isn't assigned before it is used, which is disallowed.
You should use if/else instead of testing the same condition twice.
if (...)
{
amount = 1;
}
else
{
amount = 2;
}
Now the compiler can see that every possible path through the code causes amount to be definitely assigned.
There are also a number of other advantages: the code is more concise, easier to read and more maintainable. Furthermore, there is a slight performance benefit from not doing the same check twice.
You could however also encounter an FormatException with the Convert.ToInt32() method. Consider using int.tryParse as an alternative.
Because the chances are that you won't go into any if statement and thus leaving the amount as unassigned. You will get error on this line:
int onepercent = amount /= 100;
At compile time, compiler will not be able to determine whether any of the if statement will result in true and setting of amount. To avoid this error you could do (at start) :
int amount=-1;
Now you will not get your compiler error and value of the amount will change in the if statement. P.S. ('If' is a statement not a loop)
Give this a blast:
if (!int.TryParse(inputbar.Text, out amount))
amount = 1;

False positive using string.length in if statement

I'm trying to format phone numbers. Perhaps my approach is not the best but it works with the exception of some unexpected behavior. I'm using string.length in an if statement to see if the phone number's length (stored as a string) is greater than 9. I've also tried >= 10 instead of > 9 with the same results. All works fine with 18001234567 or 7041234567. I get (800) 123-4567 or (704) 123-4567. But with 828464047 I get (82) 846-4047 rather than the number just being returned as is.
try
{
if (ANI.Length > 9)
{
char[] Number1 = { '1' };
ANI = ANI.TrimStart(Number1);
return String.Format("{0:(###) ###-####}", Convert.ToDouble(ANI));
}
else if (ANI == "")
{
return "Private";
}
else
{
return ANI;
}
}
catch (Exception ex)
{
return ex.Message;
}
Any ideas? Is there a better way to approach this?
Thanks.
If I change the code that formats the phone number to use substrings, things break, as expected.
return "(" + ANI.Substring(0, 3) + ") " + ANI.Substring(3, 3) + "-" + ANI.Substring(6, 4);
An exception is caught and "Index and length must refer to a location within the string. Parameter name: length" is returned.
I put it into a unit test method and it works. You're obviously getting an extra character added onto the string 828464047. You can debug and place a breakpoint at the IF statement and see what is actually in ANI.
A few things as well,
Don't name a variable something ambiguous like "ANI".
rename Number1 to something like "firstNumber"
A try/Catch is not needed for this statement, if you're getting an exception you're doing something that can be solved by better coding.
I can see ANI.TrimStart() in your code which leads me to suspect that you have some leading whitespace. You can probably best solve the problem by moving the trimming to outside the if.
It's pretty safe to assume that something as fundamental as String.Length works correctly. When it says your string is a certain length, your string really will be that length.
I'd check your inputs for whitespace or, perhaps you transcribed your input wrong here. The following tests pass against your code, copied and pasted:
[TestMethod, Owner("ebd"), TestCategory("Proven"), TestCategory("Unit")]
public void Ten_Digit_800_Number()
{
var myPad = new NumberFormatter();
Assert.AreEqual<string>("(800) 123-4567", myPad.FormatNumber("18001234567"));
}
[TestMethod, Owner("ebd"), TestCategory("Proven"), TestCategory("Unit")]
public void Ten_Digit_800_Number()
{
var myPad = new NumberFormatter();
Assert.AreEqual<string>("(800) 123-4567", myPad.FormatNumber("18001234567 "));
}
[TestMethod, Owner("ebd"), TestCategory("Proven"), TestCategory("Unit")]
public void TroubleString()
{
var myPad = new NumberFormatter();
Assert.AreEqual<string>("828464047", myPad.FormatNumber("828464047"));
}
The problem was stripping the leading '1' after having evaluated the length of the string. Stripping the '1' bef

C# error handling (NaN)

I have written simple math function plotter in C# using Patrick Lundin´s Math free parser.
Now, my code snippet is this:
for (float value = -xaxis; value < xaxis; value += konst)
{
hash.Add("x", value.ToString());
double result = 0;
result = parser.Parse(func, hash);...
This works perfectly for functions defined on real numbers. But, when I want want to parse functions defined only on R+ for example, ln(x), naturally parser gives NaN into result.
Now, I tried to handle it thru exception handling, like so:
for (float value = -xaxis; value < xaxis; value += konst)
{
hash.Add("x", value.ToString());
double result = 0;
try{
result = parser.Parse(func, hash);
}
catch {
count = false; //just a variable I am using to draw lines
continue; // I hoped to skip the "wrong" number parsed until I came to R+ numbers
}...
But this doesen´t work, while debugging, catch is not executed at all.
Please, what am I doing wrong? Thanks.
You say that the parser returns NaN. That is not an exception, which is what a try/catch handles. So there is no exception for the catch block, hence it never being run.
Instead, you should test your result against NaN like so:
if(double.IsNaN(result))...
It sounds as if your parser is just returning NaN, not throwing an exception. You can test for NaN using the static IsNaN method:
result = parser.Parse(func, hash);
if (float.IsNaN(result)) // assuming that result is a float
{
// do something
}
else
{
// do something else
}
You can also try turning on "Check for arithmetic overflow/underflow." It is located in your project properties, under "Build->Advanced Build Settings"
When it is turned on, arithmetic exceptions will be thrown for an overflow and underflow (instead of wrapping). It may or may not apply to the ln function. Give it a try.

Categories

Resources