Use of unassigned local variable 'month' - c#

I am getting this error after using catch-try in my code. When I hadn’t used the try-catch in my code then editor would not give this error, but when I closed my program in try-catch code then it started giving this error. My code is given bellow.
try
{
month = Int32.Parse(Console.ReadLine());
}
catch (FormatException ee)
{
Console.WriteLine(ee.Message);
}
if (month > 12 || mnth < 0)
{
Console.Write("----Incorrect Month...plz Re-");
lp_val = 1;
}

Problem : you declared a variable mnth but didnot intialize it.so if the user input is not a valid integre as input Parse function throws exception and variable mnth still is not initialized.
Solution : initialize variable mnth at the time of declaration.
Try This:
try
{
mnth=0;
mnth = Int32.Parse(Console.ReadLine());
}
catch (FormatException ee)
{
Console.WriteLine(ee.Message);
}
if (mnth > 12 || mnth < 0)
{
Console.Write("----Incorrect Month...plz Re-");
lp_val = 1;
}
OR
You can move your if block inside the try block.
try
{
mnth=0;
mnth = Int32.Parse(Console.ReadLine());
if (mnth > 12 || mnth < 0)
{
Console.Write("----Incorrect Month...plz Re-");
lp_val = 1;
}
}
catch (FormatException ee)
{
Console.WriteLine(ee.Message);
}

First off, you have two variables, month, and mnth. It looks like this is just wan error when created by posting the question here, but if it is not, make sure you resolve any typos in your code.
If an exception is raised by Int32.Parse the result will never be assigned to month, so it's not guaranteed to be assigned when you're evaluating the condition later.
The solution is to initialize the variable outside the the try block:
int month = 0;
Or to use Int32.TryParse instead of wrapping it in a try/catch:
int month;
if (!Int32.TryParse(Console.ReadLine(), out month))
{
Console.WriteLine("Unable to parse input");
}

Apart from the fact that you have variables named month and mnth, if the try-block code throws an exception, the line is not executed and mnth is not initialized to any value.

Looks like you declare month variable but you didn't initialize it.
This code gives the same error with your code;
int month;
if(month < 12)
{
//
}
That's why you should initialize it before you use it. For example use;
int month = 0;
instead
int month;

Related

Try statement doesn't always run? [duplicate]

This question already has answers here:
Use of unassigned local variable with try-catch-finally
(4 answers)
Closed last year.
i encountered an error "Use of unassigned variable 'attempt'" when i run the code below, i don't understand the reason because as i understand the try statement block always runs so the variable should be assigned by the user ? Or am i wrong ? If anyone has i fix or work around that would be helpful.
static void MagicNumber(int rndMin, int rndMax, int lives = 4)
{
Random rnd = new Random();
int rndNum = rnd.Next(rndMin, rndMax);
int attempt;
do
{
try
{
Console.WriteLine($"Remaining lives : {lives}");
Console.WriteLine($"Enter a number between {rndMin} and {rndMax} :");
attempt = int.Parse(Console.ReadLine());
}
catch
{
Console.WriteLine("Error : Enter a number !");
}
} while ((lives > 0) || (attempt < rndMin) || (attempt > rndMax));
}
MagicNumber(1, 40, 5);
The variable attempt will not get assigned a value if an exception gets thrown in your try block, so will be unassigned when it gets to the evaluation in your while. The two possible solutions are:
Initialize it to a default value when you declare it.
Assign it some value in your catch block.
Either one should work.
An exception can be thrown in the try block prior to setting a value for attempt. You handle the exception so it's then possible for attempt to be referenced before being assigned a value.
Best practice is to always assign an initial value to variables.

Try... catch: test if statement is true

I want to test if my decimal Add is smaller than MAXVALUE and bigger than MINVALUE, with a Try... Catch Method. And if the numbers are bigger than MAXVALUE or smaller than MINVALUE the code should throw an Exception.
But my Code isn't working.
public static decimal Add(decimal number1, decimal number2)
{
decimal Add = number1 + number2;
try
{
Add > RESULT_MAXVALUE;
Add < RESULT_MINVALUE;
}
catch(Exception)
{
//Do Stuf
}
}
I don't want to use if... else!
It depends on the language that you're using, but the convention is that the try block contains statements that can throw exceptions, and thrown exceptions are caught by the catch() blocks following the try. You need to explicitly throw an exception before it can be caught.
It looks like you're using C#. Consider reading https://msdn.microsoft.com/en-us/library/0yd65esw.aspx for more information about try-catch statements in C#.
Using exceptions in your case may not be necessary. Consider using an if statement, like this:
decimal result = a + b;
if ((result > MAX_VALUE) || (result < MIN_VALUE))
{
// Do stuff.
}
But to answer your question more directly, here's how you would do it using exceptions:
decimal result = a + b;
try
{
if ((result > MAX_VALUE) || (result < MIN_VALUE))
{
throw new System.ArithmeticException(); // Or make an exception type.
}
}
catch (System.ArithmeticException e)
{
// Do stuff.
}
Or perhaps you would throw the exception in Add, but not catch it. Then it would be the caller's responsibility to handle the exception, or let the program crash. That would look like this:
// Adds two numbers. Throws a System.ArithmeticException if the result
// is greater than MAX_VALUE or less than MIN_VALUE.
public static decimal Add(decimal a, decimal b)
{
decimal result = a + b;
if ((result > MAX_VALUE) || (result < MIN_VALUE))
{
throw new System.ArithmeticException(); // Or make an exception type.
}
}
And callers would need to wrap calls to Add in a try {} catch if they expect some results to be bigger than MAX_VALUE or less than MIN_VALUE (or, callers could not catch the exception and the program would crash).

Try {} Catch {} Not working as it should in C#

I have a try {} catch {} for each line my user inputs something, this is to ensure it's in the right format/range/acceptable. However it doesn't seem to... well work! Here is one of my examples.
string userAnswer;
bool errorHandling = true;
while (errorHandling){
try{
userAnswer = Console.ReadLine();
if (userAnswer == "1") {
singleGrade.grapher(acount, bcount, ccount, dcount, ecount, fcount);
}else{
if (userAnswer == "2"){
readIn.Classes(SingleGrade[1]);
}else{
if (userAnswer == "3"){
countAll.allGrades(multiGrade);
} else{
errorHandling = false;
}
}
}
}
catch (FormatException a){
Console.WriteLine(a.Message);
//Console.WriteLine("Error - please enter a number between 1 & 6.");
}
} // end of While loop
If someone could please explain to me why no error is caught when an invalid number is placed/not in the correct format.
There is no FormatException being thrown because valid strings are being entered. If you were to convert the user input to an integer, for example, that would throw a FormatException. But since you are leaving it as a string, no exception is being thrown.
However, since you are really only trying to restrict user input, and nothing truly exceptional is happening here, you should probably just handle it through you application logic.
What you are really looking for is probably something like this:
bool errorHandling = true;
while (errorHandling)
{
string userAnswer = Console.ReadLine();
switch (userAnswer)
{
case "1":
singleGrade.grapher(acount, bcount, ccount, dcount, ecount, fcount);
errorHandling = false;
break;
case "2":
readIn.Classes(SingleGrade[1]);
errorHandling = false;
break;
case "3":
countAll.allGrades(multiGrade);
errorHandling = false;
break;
// cases for 4, 5, and 6...
default:
Console.WriteLine("Error - please enter a number between 1 & 6.");
break;
}
} // end of While loop
You're not throwing and exception when the number is invalid, you're just handling a bunch of if statements - thus, since there is no throw statement, nothing can hit the catch statement, and insteadyou're seeing what we colloquially call a "Fall through error" - logic is proceeding past where it should.
If you want an exception when input is invalid, just add a throw new FormatException to the end of the if statements, so you get a "if we make it here there's a problem" behaviour.
The reason is that you are grabbing a string, and not trying to convert it to anything else, so there is no FormatException.
I would get away from using the try / catch for input validation, and instead use the TryParse method of the Int type.
What I usually do is write a separate function to get validated input from the user, then call that from my main code. In this case, since you have upper and lower bound requirements, you might consider writing something like this:
public static int GetBoundedIntFromUser(int minVal, int maxVal)
{
if (minVal >= maxVal)
{
throw new ArgumentException("minVal must be less than maxVal.");
}
int input;
while (true)
{
Console.Write("Please enter a number from {0} to {1}: ", minVal, maxVal);
if (int.TryParse(Console.ReadLine(), out input)
&& input >= minVal && input <= maxVal)
{
break;
}
Console.WriteLine("That input is not valid. Please try again.");
}
return input;
}
Then you can just call it from your main code (without any try catch), like:
switch (GetBoundedIntFromUser(1, 3))
{
case 1:
singleGrade.grapher(acount, bcount, ccount, dcount, ecount, fcount);
break;
case 2:
readIn.Classes(SingleGrade[1]);
break;
case 3:
countAll.allGrades(multiGrade);
break;
default:
break;
}

Where does an empty return statement lead in C#?

For the code below, both WriteLine results outputs are 30.
I do not know why the second result is 30 too.
I think if the value is -1, then the program runs out of the curly brace { return; }, and moves to the next line after {}.
Is it correct?
class Program
{
static void Main(string[] args)
{
Person pp = new Person();
pp.Age = 30;
// Output is 30
Console.WriteLine("the age is {0}", pp.Age);
pp.Age = -1;
// Output is 30 again
Console.WriteLine("the age is {0}", pp.Age);
}
}
class Person
{
private int age;
public int Age
{
set
{
if (value < 0)
{
// An empty return statement
return;
}
// if the value is -1, does it go through this line?
this.age = value;
}
get
{
return this.age;
}
}
}
The return keyword returns control out of the function (regardless of how many nested scopes you are in). This "bail-out" approach is one reason why early returns are considered bad practice. So basically, your program flows like this:
Call setter with 30
value > 0, skip what is in {}
Set backing field to 30
Print property (still 30)
Call setter with -1
value < 0, execute what is in {}
Return, function execution stops and returns to the caller
Print property (still 30 since nothing got set)
If you are doing validation in your setter, throwing an exception is a much better approach.
The return statement exits the property setter before setting the age value. Nothing is returned, as a setter is like a void method. It looks like you don't want to set an age less than 0, which makes sense.
Some apps decide to throw an ArgumentException in cases like this rather than silently failing.
Your setter is just returning if the value is less than 0 so you never set the age when you attempt to set it as -1. The setter should be:
public int Age {
set { age = value; }
}
Unless you don't want to set age if it's less than 0 you would want to throw an exception:
public int Age {
set {
if (value < 0)
throw new ArgumentException();
age = value;
}
}
return will cause a method to immediately exit a method, not merely leave a scope in { }.
There are some cases you want to exit a scope, but not a method. That is done with break, but works in loops.
for (;;)
if (condition)
break; // breaks out of the loop
I think what you are trying to do is protect age from negative values. I recommend using exceptions.
public int Age
{
set
{
if (value < 0)
throw new InvalidArgumentException("Age cannot be negative");
age = value;
}
get
{
return age;
}
}

Why does this simple method not work?

It must be simple, but i can't seem to find the explanation. Why does the following generates these errors:
Unreachable code detected (on result++)
WindowsFormsApplication1.Form1.GetResult(int, int): not all code paths return a value
private int GetResult(int start, int end)
{
for (int result = start; result < end; result++)
{
return result;
}
}
Anyone who could please help me out? Thnx in advance :)
EDIT:
First of all, thanks for the many (fast) replys. Stupid of mine...but i didn't see it.
And sorry, i needed to be a little more precise of what it is i wanted to accieve..
I need a method that adds 1 to a value (result) starting from the given start value (int start) untill it reaches another value (int end).
So it might also add directly to start integer if I’m not mistaking. And return that value?
Because your method is returning an int type, and the compiler can't determine whether you will get inside the loop.
What if the result is greater than or equal to end, in that case, the statement inside the loop will not execute and hence you get the error.
From MSDN - For Loop
Because the test of a conditional expression occurs before the
execution of the loop, a for statement executes zero or more times.
This gives you the reason behind the error "not all code path returns a value", because if the for loop executes 0 times then the method will not return anything
For warning "Unreachable code detected", the reason is that your update expression result++ executes after the execution of the for block. Since your for block contains return statement, you will never reach your update expression
What a clever compiler!
for (int result = start; result < end; result++)
{
return result;
}
... is equivalent to:
int result = start;
while(result < end) {
return result;
result++;
}
If start >= end as we go into this code, the content of the while loop will never run. In that case, the program flow won't hit a return statement: Not all code paths return a value.
If start < end as we enter the function, the program flow will go into the loop, hit the return statement, and the method will return. It can't hit the result++ statement. Unreachable code detected.
In response to your edit:
public int getResult(int start, int end) {
int result = start;
while(result < end) {
result++;
}
return result;
}
... does what you describe. However it's a wasteful way to get that result. If start=0 and end=1000000, the program will loop a million times.
You'd get exactly same result more efficiently with:
public int getResult(int start, int end) {
if(end > start) {
return end;
} else {
return start;
}
}
Or even:
public int getResult(int start, int end) {
return Math.Max(start,end);
}
(Although it's still not clear what you want the result to be if start > end)
There are two different cases at the beginning of the method:
Case start < end: You always return result immediately in the
first loop run. Therefore result is never going to be incremented.
Case start >= end: You never enter the loop, therefore you'd need
another return statement outside of it.
It is obvious that result++ is unreachable. You would reach it after the first execution of the loop, if any - but in this very first execution of the loop, you return, thus exiting the function.
For the second part of the question, see Habib's answer.
private int GetResult(int start, int end)
{
int result = 0;
for (result = start; result < end; result++)
{
return result;
}
return result;
}
This way the function should work.
You are calling the for loop.
It sets result=start compares if condition is true
and then returns result.
How shall it ever reach result++ ?
=Unreachable code detected (on result++)
could be that the loop never enters when result > end so
=not all code paths return a value
lets assume that the condition "result < end" is true. The control will then go the statement inside the loop. Since it is a return statement, control will come out of the function/method GetResult. So, the control never reaches to "result++". That is why you get - unreachable code.
Let me know, if it is useful.
All the best !!!
If you add a return statement after the for loop it will compile without errors.
private int GetResult(int start, int end)
{
int result = 0;
for (result = start; result < end; result++)
{
return result;
}
return result;
}
This function returns start if start < end, else it doesn't return anything.
What was the intention of your method ?
Let us consider a scenario in which your condition result < end got failed . so the control
will not enter into loop and will come out of loop. but outside there is no return statement so what would it return as other end is expecting some integer to be return , so that's why you are getting error.
this will work :-
private int GetResult(int start, int end)
{
for (int result = start; result < end; result++)
{
return result;
}
return 0;
}
if the start > end value ,the code inside the loop will never be executed and hence there wont be anything to return from the function and hence you will get those errors.
Moreover there is no point of using for loop as u did since in the first step itself if start
private int GetResult(int start, int end)
{
if(start<end)
return start;
return -1;
}
I don't think for and return do what you think they do. As I read your code, it could be dumbed down to this:
private int GetResult(int start, int end)
{
if (start < end)
{
return start;
}
else
{
return 0; // or another default for when start >= end
}
}
Because return will, well, return from the method. Since the first iteration of the loop (if start < end) will immediately return result, which has been set to the value of start.
As your code shows, the else part is missing. Therefore the compiler doesn't know what you want to return when start >= end and also result++ is never called because you directly return, so it'll throw the error and warning shown.
Because if start >= end, the loop will not be entered
private int GetResult(int start, int end)
{
for (int result = start; result < end; result++)
{
return result;
}
return -1; // Path here exists
}
Out of interest, if you want to return each of the integers between start and end, you should look at yield return instead:
private IEnumerable<int> GetResult(int start, int end)
{
for (int result = start; result < end; result++)
{
yield return result;
}
// Now we don't need a return, because the loop will eventually complete
}
Edit Looking at the comments, OP may well want a sequence of numbers.
The above method can be iterated
foreach (int anInt in GetResult(40, 50))
{
Console.WriteLine(string.Format("Next value is {0}", anInt));
}

Categories