How to terminate a method execution Midway in C#? - c#

I need to exit from a method when a certain condition is reached. The other lines of code should not be executes after exit Condition is reached. what is the best way for this I have tried to use Environment.Exit(0), but it causes problem in my logic.
Exit(0) does not seem to work unless in a loop

We have two possibilities: normal (return) and abnormal (throw) termination:
public static int Factorial(int value) {
// We can't compute factorial for negative and too large values
if (value < 0 || value > 12)
throw new ArgumentOutOfRangeException(nameof(value)); // Abnormal termination
if (value == 0)
return 1; // Normal termination: special case in which we know the answer
...
}

The "return" statement exits condition-blocks aswell as loops and methods.
public void myMethod(int a){
if( 1 == a) {
return;
}
// do something with a
}

As some people have already said before me, return is the way to go.
Here is an example where an if statement compares two integers and returns if they are equal:
public void isEqual(int a, int b) {
if (a == b) {
Console.WriteLine("Integers are equal");
return; //Return to executing the rest of the program.
}
else {
Console.WriteLine("Integers are not equal");
}
}

Related

Is there an integer i where i<2 && i>10?

if(i<2 && i>10){
//code here will never be reached or what?
}
Just in case of an integer overflow maybe?
Edit: I wrote this not knowing c# is the language used. I've used C++ but I believe that the principle is also valid for c#.
there is no single integer that satisfies the condition
the compiler may well optimize away the body of the if condition (see here for an example on compiler explorer)
however, in the case of i being volatile it is possible that the value of i changes between the i<2 and the i>10 tests. In this case the if body can be reached.
However, though it may be theoretically possible it is highly unlikely that this was the intention.
Here's my example code
#include <iostream>
using std::cout;
void foo(int i)
{
if (i < 2 && i > 10)
{
cout << "The impossible happened in foo\n";
}
}
void bar(volatile int i)
{
if (i < 2 && i > 10)
{
cout << "The impossible happened in bar\n";
}
}
It is indeed possible for some c# (assuming c# because it's tagged... not assuming integer even if it's tagged because the right-hand comparison is still an integer, so it matches the tags! ;-) ) code to go into that if... take:
public class Foo {
public static bool operator> (Foo a, int b) {
return true;
}
public static bool operator< (Foo a, int b) {
return true;
}
}
Then:
Foo i = new Foo();
if(i<2 && i>10){
Console.WriteLine("Pass!");
}
Guess the output? Check it out here
Another way, with no extra classes or operator overloading:
private static bool odd;
public static int i { get { odd = !odd; return odd ? 1 : 11; } }
Check it out
Otherwise, it could also happen if multithreading (if the value of i changes bewtween the comparisons) unless you apply correct locking

Checking number range not working

private bool DataValidation(string Checker)
{
int i;
if (Int32.TryParse(Checker, out i))
{
return true;
}
else
{
return false;
}
}
private void NumberChecker()
{
if (int.Parse(txtRank.Text) >= 0 || int.Parse(txtRank.Text) <= 50)
{
errorProvider1.SetError(txtRank, string.Empty);
errorProvider1.Clear();
}
else
{
errorProvider1.SetError(txtRank, "Between 1 and 50 please!");
}
}
private void txtRank_Validating(object sender, CancelEventArgs e)
{
if (DataValidation(txtRank.Text) == false)
{
errorProvider1.SetError(txtRank, "Must be numeric!");
}
else
{
errorProvider1.SetError(txtRank, string.Empty);
errorProvider1.Clear();
}
NumberChecker();
}
I've been trying to get this to work for about 4 hours, can someone please tell me why it keeps saying "String in the wrong format" I've tried all of this inside the the validation event, nothing I do is working. I am not understanding why.
Update:
private void txtRank_Validating(object sender, CancelEventArgs e)
{
if (DataValidation(txtRank.Text) == false)
{
errorProvider1.SetError(txtRank, "Must be numeric!");
}
else
{
errorProvider1.SetError(txtRank, string.Empty);
errorProvider1.Clear();
}
if (Convert.ToInt32(txtRank.Text) >= 0 && Convert.ToInt32(txtRank.Text) <= 50)
{
errorProvider1.SetError(txtRank, string.Empty);
errorProvider1.Clear();
}
else
{
errorProvider1.SetError(txtRank, "Between 1 and 50 please!");
}
}
if i use the code above, i can either do one or the other, but i have to comment out a section of code in order to do that.
You're doing a lot of stuff here that isn't necessary at all.
First off: Assuming that the if statement in your DataValidation method is only intended to have the return true and return false, the if statement is totally unnecessary. You could just say return Int32.TryParse(Checker, out i); and it would do the exact same thing. In fact, you could remove the int i in the first place, and just do this:
private bool DataValidation(string Checker) {
return Int32.TryParse(Checker, out int i);
}
out int i creates a temporary variable... and since the DataValidation method is now a single method call, you may realize that the whole method is now unnecessary. You could simply replace any call to DataValidation(someString) with Int32.TryParse(someString, out int i) with no side effects.
Moving on to your NumberChecker method, the error becomes immediately apparent:
if (int.Parse(txtRank.Text) >= 0 || int.Parse(txtRank.Text) <= 50)
This is the only place in your code where you are parsing a string without checking to ensure that it's a number first. Evidently, txtRank.Text is a string that is not a proper number. This is actually where TryParse would come in handy.
I'm going to assume that you don't know exactly what TryParse does and that you were only using it as an error checker, which is okay, because the function of out arguments aren't immediately apparent.
The out keyword, effectively, allows a function to change the thing that was passed in. Take the following code snippet:
public static void Main(string[] args)
{
String foo = "abc";
DoSomething(out foo);
Console.WriteLine(foo);
}
private static void DoSomething(out String something)
{
something = "def";
}
Despite DoSomething not returning a value, the Console.WriteLine(foo); will write def rather than abc. Int32.TryParse uses this to its advantage: It returns a bool that says whether the operation was successful or not. And if it was successful, it stores the result in the variable used as the out argument.
As such, your NumberChecker method should look something like this:
private void NumberChecker()
{
int num = null;
if (Int32.TryParse(txtRank.Text, out num) {
// if TryParse returns true, then we have a result in `num`.
if (num >= 0 && num <= 50)
{
errorProvider1.SetError(txtRank, string.Empty);
errorProvider1.Clear();
}
else // txtRank.Text is a number, but is not within the range
{
errorProvider1.SetError(txtRank, "Between 1 and 50 please!");
}
}
else // txtRank.Text is not a number to begin with
{
errorProvider1.SetError(txtRank, "txtRank.Text is not a number!");
}
}
Worth noting: Since NumberChecker() can now handle the case of invalid text like txtRank_Validating() used to, you can now remove txtRank_Validating() as well. NumberChecker() is now the only necessary code.
One final thing worth noting: In your original code, although your txtRank_Validating() has if statements for in case txtRank.Text was not a number, the reason it was still failing was because NumberChecker() was called at the end of the method whether the text was a number or not. In that sense, the easiest solution would have just been to move the NumberChecker(); call to after errorProvider1.Clear(); inside the else block. But I think the rest of the details in this answer are worth taking note of.

Unreachable code detected in the for loop

I'm trying to find out if a number is prime or not. But I've got an error of "unreachable code detected", which I think is effecting the error of "not all code paths return a value". The error seems to occur in the for loop at i++. Can anyone help me please?
static void Main(string[] args)
{
Console.WriteLine(isPrime(10));
}
public static bool isPrime(int n)
{
for (int i = 2; i < n; i++)
{
if (n % i == 0)
{
return false;
}
return true;
}
}
"Unreachable code detected" means that some code can never be executed. Consider:
int something()
{
if (true)
return 1;
else
return 2; //Obviously we can never get here
}
"Not all code paths return a value" means that you've defined a method with a return value (like "bool" in your example) and there is some way for the method to execute without returning a value.
Consider:
int something(bool someBool)
{
if (someBool)
return 1;
//if someBool == false, then we're not returning anything. Error!
}
Your code has two problems:
You have return true inside the for loop (outside of any conditional). Because return immediately exits the function (returning control to the caller) the i++ statement of the for loop will never get executed (hence your bug). You likely intended for that to be outside the for loop.
Another problem with that being in the loop is that the loop is not guaranteed to execute. If the n passed was 2 or less, you would skip the loop entirely, and there is no return statement in that case. This isn't allowed (since you always need to return a value from a non-void function) so you get a compiler error.
Below is an example of how to get this return working with a for loop and embedded If condition.
private bool WinOneLevelOne()
{
//For loop to check all the items in the winOne array.
for (int i = 0; i < winOne.Length; i++)
{
//If statement to verify that all the gameobjects in the array are yellow.
if (winOne[i].gameObject.GetComponent<MeshRenderer>().material.color != Color.yellow)
{
//Keeps the boolean at false if all the gameobjects are not yellow.
return false;
}
}
return true;

assigning value to bool inside while loop

I know this is a very newbie C# question but I am implementing a small program which does the following:
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
bool isRun = false;
int number = 0;
while (isRun = (true) && number < 3)
{
++number;
Console.WriteLine("Number = {0}", number.ToString());
Console.WriteLine();
}
Console.WriteLine(isRun.ToString());
Console.ReadLine();
}
}
}
At the end of the while loop, I would have expected the bool value to be true, but is is printed to be false. Why is that? Is this different from C++ where I would have done something like and the same thing in C# is giving me false
while(number<3)
{
is = true;
}
if(is){
cout<<true;
}
The reason you're seeing this behavior is due to the operator precedence involved. Here the && binds more strongly than = so the code in the loop is actually bound as the following
while (isRun = (true && number < 3)) {
...
}
Once number > 3 the && expression is false and is assigned into the isRun value and simultaneously terminates the loop. Hence once the loop exits you will see isRun as false
To get the behavior you are looking for you will need to manually correct the precedence with parens.
while ((isRun = (true)) && number < 3) {
...
}
Note: In general, as #Servey pointed out, the assignment of locals to expressions inside the loop predicate is considered bad practice. Many C# users would actually be surprised that code compiles at all because they've been conditioned to only use == in loops.
It's more idiomatic to simply set isRun to true on the first line of the loop for this pattern.
while (number < 3) {
isRun = true;
...
}
The problem is that you have set you boolean variable to false and without assigning it back to true, in while loop you are matching it against the value true, thus it fails in every case.

How to exit from a C# recursive method which has return type

My code is like the below one,
public object GetObjectValue(object obj, int condition)
{
if(condition > 10)
{
//exit from method
// return; gives compiler error.
}
else
{
GetObjectValue(obj,condition); // like this i need to use recursive call.
//Do stuffs
}
}
How to exit from this method. Help me.
Some points:
You need to return something in either case. Even if you return null on if(condition > 10), your next compilation error will say you need to return a value on every path (actually, that's the same compilation error)
GetObjectValue(obj,condition); may result in an infinite recursion - you call it with the same values over and over.
You cannot "do stuff" after a return statement - that marks the end of the executed code (unless you have a finally block, but that's another subject). If you don't want to return that value that's also great, but you probably want to use it somehow: object returnedValue = GetObjectValue(obj, condition);
You may be looking for something like:
public object GetObjectValue(object obj, int condition)
{
if(condition > 10)
{
//exit from method
return null;
}
else
{
IChild current = (IChild)obj
//Do stuffs HERE
return GetObjectValue(current.Parent, condition + 1); recursive call.
}
}
You need to return an object reference, or null.
public object GetObjectValue(object obj, int condition) {
if (condition > 10) {
return null;
} else {
return GetObjectValue(obj, condition);
}
}
Be aware though, that this method is very prone to a stack overflow error because any value of condition less than or equal to 10 will never reach the base case, or terminating condition. Recursive methods need a case that returns a value without calling itself.
public object GetObjectValue(object obj, int condition) {
if (condition > 10) {
return null;
} else {
return GetObjectValue(obj, condition++);
}
}
Now condition is incremented, so when the method is called, it will eventually progress towards a value greater than 10, satisfying the condition and returning null. This is still a useless method though, because it can only ever return the same value for any input; the only difference will be how many recursive calls it makes before returning null.
You are supposed to return an object:
public object GetObjectValue(object obj, int condition)
Either change the return type:
public void GetObjectValue(object obj, int condition)
Or use a valid return statement:
if(condition > 10)
{
//exit from method
return null;
}
You have specified the return type as object, so have to specify the valid return type. Try the below code change,
public object GetObjectValue(object obj, int condition)
{
if (condition <= 10)
{
GetObjectValue(obj, condition);
}
return null; //return whatever object you have to return
}

Categories

Resources