I have a piece of code where in I have an if block which when satisfied the flow goes into it and in there are nested if and else, if it does not satisfies any of the if block it should go into the else block but the problem i am facing is that it satisfies one if block and then goes into else as well. this is creating redundancy in my code.
it like this
if(condition = true)
{
if(condition1 == true)
{}
if(condition2 == true)
{}
else
{}
}
Now it satisfies condition 1 and then after performing if block operations goes into else also.
Please help. Code is in C#
You probably need something like this (notice else if with condition2):
if(condition)
{
if(condition1)
{}
else if(condition2)
{}
else
{}
}
You can skip '== true' in conditions.
get rid of the ==true's its just going to lead to a mistake like you made on the first line. also, add in else statements.
if (condition)
{
if (condition1)
{ }
else if (condition2)
{ }
else
{ }
}
As RaYell says, you need an extra "if" block. Here's a short but complete example to demonstrate:
using System;
public class Test
{
static void Main()
{
bool condition = true;
bool condition1 = true;
bool condition2 = false;
if (condition)
{
if (condition1)
{
Console.WriteLine("condition1");
}
// Note the "else if" here.
else if (condition2) {
Console.WriteLine("condition2");
}
else
{
Console.WriteLine("neither");
}
}
}
}
This prints "condition1" but not "neither".
If that isn't what you want, please clarify your question.
Put it like this
if(condition == true) {
if(condition1 == true) {}
else if(condition2 == true) {}
else {}
}
Ya you can use else if.Also you can write
if (condition==true) as if(condition) simply
For example
int i=2;
int j=3;
int k=4;
bool condition=k>1;
bool condition1=j<i;
bool condition2=j>i;
if (condition)
{
if (condition1)
{ }
else if (condition2)
{ }
else
{ }
}
Then, why don't you split up your code in methods, so you can do this:
if( condition)
{
if( condition1 )
{
DoSomethingForSituation1();
}
else
{
DoSomethingForSituation2();
}
}
else
{
DoSomethingForSituation1();
}
Also, when I look at it this way, you could say that 'condition' is redundant ?
Because either way, condition1 will always be true in some scenario ?
if( condition1 )
{
DoSomethingForSituation1();
}
else if( condition2 )
{
DoSomethingForSituation2();
}
Related
How Can i check if it's the first iteration in my while loop in C#?
while (myCondition)
{
if(first iteration)
{
//Do Somthin
}
//The rest of the codes
}
bool firstIteration = true;
while (myCondition)
{
if(firstIteration )
{
//Do Somthin
firstIteration = false;
}
//The rest of the codes
}
You could move the do something out of the loop. Only guaranteed to do the exact same if the "Do Somthin" does not change myCondition. And myCondition test is pure, i.e. no side effects.
if (myCondition)
{
//Do Somthin
}
while (myCondition)
{
//The rest of the codes
}
use a counter:
int index = 0;
while(myCondition)
{
if(index == 0) {
// Do something
}
index++;
}
You could make a bool outside the loop
bool isFirst = true;
while (myCondition)
{
if(isFirst)
{
isFirst = false;
//Do Somthin
}
//The rest of the codes
}
Something like this?
var first=true;
while (myCondition)
{
if(first)
{
//Do Somthin
}
//The rest of the codes
first=false
}
Define a boolean variable:
bool firstTime = true;
while (myCondition)
{
if(firstTime)
{
//Do Somthin
firstTime = false;
}
//The rest of the codes
}
You can do that by workarounds, like:
boolean first = true;
while (condition)
{
if (first) {
//your stuff
first = false;
}
}
Try something like this:
bool firstIteration = true;
while (myCondition)
{
if(firstIteration)
{
//Do Something
firstIteration = false;
}
//The rest of the codes
}
I would recommend using counter variable for this, or a for loop.
E.G.
int i = 0;
while (myCondition)
{
if(i == 0)
{
//Do Something
}
i++;
//The rest of the codes
}
Still learning, but this way came to me, have not used this before myself but I plan to test and possibly implement in my project:
int invCheck = 1;
if (invCheck > 0)
{
PathMainSouth(); //Link to somewhere
}
else
{
ContinueOtherPath(); //Link to a different path
}
static void PathMainSouth()
{
// do stuff here
}
static void ContinueOtherPath()
{
//do stuff
}
This is fairly simple method. I use entity framework to get some data and then check some values in a if statement. However right now the method is marked with red.
This is my method:
private bool IsSoleInProduction(long? shoeLastID)
{
if (shoeLastID == null)
{
MessageBox.Show(Resources.ERROR_SAVE,
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
ISoleService soleService =
UnityDependencyResolver.Instance.GetService<ISoleService>();
List<Sole> entity =
soleService.All().Where(s => s.ShoeLastID == shoeLastID).ToList();
if (entity.Count() != 0)
{
foreach (var items in entity)
{
if (items.Status == 20)
{
return true;
}
else
{
return false;
}
}
}
else
{
return false;
}
}
What am I missing?
You need to take advantage of LINQ with Any, replace your code:
if (entity.Count() != 0)
{
foreach (var items in entity)
{
if (items.Status == 20)
{
return true;
}
else
{
return false;
}
}
}
else
{
return false;
}
with simpler code:
return entity.Any(item => item.Status == 20);
Or even better performance:
return soleService.All()
.Any(s => s.ShoeLastID == shoeLastID
&& s.Status == 20);
Edit: With you comment, below code is what you need:
List<Sole> entity = soleService.All()
.FirstOrDefault(s => s.ShoeLastID == shoeLastID);
return entity == null ? false : entity.Status == 20;
If there's no item in your entity collection, then neither of the containing if/else branches will be executed. In this case there's no return statement anymore, because the else part won't be executed, and outside your foreach you have no return statement.
The compiler does not "see" that if
entity.Count() != 0
then your loop
foreach (var items in entity)
will run at least once. Therefore it sees a possibility of running the forech zero times, and not running the else block.
Suppose first time the entity is enumerated, it yields some (finite number of) items. Then the Count will be non-zero. Then suppose next time the same entity is enumerated then it yields no items! That would cause your code to "fall through" without returning.
It is very probably that you can guarantee that the source yields the same number of items each time it is re-enumerated. But the compiler cannot.
Solution: Just skip if (entity.Count() != 0) and do foreach right away.
You haven't retrun anything from this code block
if (entity.Count() != 0)
{
foreach (var items in entity)
{
if (items.Status == 20)
{
return true;
}
else
{
return false;
}
}
// return someting
}
You might consider doing the following. This will adhere to the "single exit-point" principle (which can sometimes help improve code clarity), and ensure you have a default value in any case:
private bool IsSoleInProduction(long? shoeLastID)
{
// The main change: A default value, assuming "no":
var isSoleInProduction = false;
if (shoeLastID == null)
{
MessageBox.Show(Resources.ERROR_SAVE,
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
isSoleInProduction = false;
}
ISoleService soleService =
UnityDependencyResolver.Instance.GetService<ISoleService>();
List<Sole> entity =
soleService.All().Where(s => s.ShoeLastID == shoeLastID).ToList();
if (entity.Count() != 0)
{
foreach (var items in entity)
{
if (items.Status == 20)
{
isSoleInProduction = true;
}
else
{
isSoleInProduction = false;
}
}
}
else
{
isSoleInProduction = false;
}
return isSoleInProduction;
}
What will be your entity.Count() is not 0 and your entity doesn't have any items?
That means your if block will work but foreach part will not work. Since your if part doesn't have any return statement, that's why you get an error.
You should put return statement in your if part.
if (entity.Count() != 0)
{
foreach (var items in entity)
{
if (items.Status == 20)
{
return true;
}
else
{
return false;
}
}
//return true or false
}
If your entity collection has no elements you will not reach a return statement - you need to add a return false forexample as last statement
As the error states there can be cases in which none of your return clause is evaluated (e.g. if there are no elements in your list).
To quickly solve it you can put a default return statement, for example by moving the last return clause outside the else statement. But it really depends on the behavior you'd expect.
private bool IsSoleInProduction(long? shoeLastID)
{
if (shoeLastID == null)
{
MessageBox.Show(Resources.ERROR_SAVE, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
ISoleService soleService = UnityDependencyResolver.Instance.GetService<ISoleService>();
List<Sole> entity = soleService.All().Where(s => s.ShoeLastID == shoeLastID).ToList();
if (entity.Count() != 0)
{
foreach (var items in entity)
{
if (items.Status == 20)
{
return true;
}
else
{
return false;
}
}
}
return false;
}
The compiler can't guarantee that the first call to Count means that the foreach will loop at least once (with good reason, because you could, if you wished, create a collection where this wasn't true). You can do this instead (with no need for the outer if):
foreach (var items in entity)
{
if (items.Status == 20)
{
return true;
}
else
{
return false;
}
}
return false;
hey guys m running into a problem, i have a forloop n in that i call a function, and in that function i have a if condition, i want to skip 1 loop if condition gets true, for this problm i was thinkin' to use goto statement but as i read in many forums that goto statement is an evil... can it be solved without using goto statement, ne ideas i dn't want to use 'goto'
for(int i=0;i<gridview.rows.count-1;i++)
{
//some operation;
aFunction(param1,param2);
}
public void aFunction(param1,param2)
{
//some operation;
if (!Regex.IsMatch(RechargeText, "successfully"))
{
RechargeStatus = "Failed";
Program.sp.SoundLocation =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) +
"/aimlife_error.wav";
Program.sp.Play();
}
else if (Regex.IsMatch(RechargeText, "Processing") || Regex.IsMatch(RechargeText, "Not"))
{
// here i need to skip the Loop
}
else
{
Program.sp.SoundLocation =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) +
"/aimlife_success.wav";
Program.sp.Play();
}
Program.StatusMessage = "Recharge Successful";
TextFill();
}
Actually there are some error list that are accepted errors, so i dn't need to update that in db, So my TextFill(); function shud not run for accepted errors
Snippet Edited
Simple, have the method return a bool. Then you can do:
for(int i=0;i<gridview.rows.count-1;i++)
{
//some operation;
if (aFunction(param1,param2)) break;
}
goto won't help you anyway. Basically you can't continue from a different method at all. The only simple way you can keep roughly your current flow is something like this:
bool shouldSkipNext = false;
for (int i = 0; i < gridview.Rows.Count - 1; i++)
{
if (shouldSkipNext)
{
shouldSkipNext = false;
continue;
}
// some operation
shouldSkipNext = aFunction(param1, param2);
}
public bool aFunction(param1,param2)
{
if (abc)
{
return true;
}
// Other stuff
return false;
}
Note that this will skip the entirety of the next iteration of the loop - which isn't the same as just continue. If you have more code after the call to aFunction and you want to skip that (which is the equivalent of continue) then it's simpler:
for (int i = 0; i < gridview.Rows.Count - 1; i++)
{
// some operation
if (aFunction(param1, param2))
{
continue;
}
// Other stuff which will sometimes be skipped
}
All you want to do is skip executing the TextFill() function when the condition if (Regex.IsMatch(RechargeText, "Processing") || Regex.IsMatch(RechargeText, "Not")) is true, thats all right?
You can simply return at that if condition, which will work out as you want:
else if (Regex.IsMatch(RechargeText, "Processing") || Regex.IsMatch(RechargeText, "Not"))
{
return;
} .... // rest of the code as it is
now when the above condition works out as true it will return to the for loop and go with the next iteration and so on...
Cheers
for(int i=0;i<gridview.rows.count-1;i++)
{
//some operation;
if (!aFunction(param1,param2)) continue;
}
public bool aFunction(param1,param2)
{
//some operation;
if (!Regex.IsMatch(RechargeText, "successfully"))
{
RechargeStatus = "Failed";
Program.sp.SoundLocation =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) +
"/aimlife_error.wav";
Program.sp.Play();
}
else if (Regex.IsMatch(RechargeText, "Processing") || Regex.IsMatch(RechargeText, "Not"))
{
Program.StatusMessage = "Recharge Successful";
TextFill();
return false;
// here i need to skip the Loop
}
else
{
Program.sp.SoundLocation =
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) +
"/aimlife_success.wav";
Program.sp.Play();
}
Program.StatusMessage = "Recharge Successful";
TextFill();
return true;
}
If your code as posted is exactly how it is, then you could simply return, as the loop has no other operations.
No, it can not be solved with a goto... thankfully.
There is nothing that you can do inside the method that will change the control flow in the loop, you have to return something from the method and use that in the code of the loop:
for(int i = 0; i < gridview.rows.count - 1; i++) {
//some operation;
if (aFunction(param1,param2)) {
// do something more here
}
}
public bool aFunction(param1,param2) {
//some operation;
if(abc) {
//skip the current for-loop i.e i want to do "continue" here;
return false;
} else {
//normal
return true;
}
}
public static void main(String[] args) {
int param1 = 0, param2 = 0;
getResult(param1, param2);
}
public static void getResult(Object param1, Object param2) {
for (int i = 0; i < gridview.rows.count - 1; i++) {
if (!Regex.IsMatch(RechargeText, "successfully")) {
RechargeStatus = "Failed";
Program.sp.SoundLocation = System.IO.Path
.GetDirectoryName(System.Reflection.Assembly
.GetExecutingAssembly().Location)
+ "/aimlife_error.wav";
Program.sp.Play();
} else if (Regex.IsMatch(RechargeText, "Processing")
|| Regex.IsMatch(RechargeText, "Not")) {
// just skip here then
continue;
} else {
Program.sp.SoundLocation = System.IO.Path
.GetDirectoryName(System.Reflection.Assembly
.GetExecutingAssembly().Location)
+ "/aimlife_success.wav";
Program.sp.Play();
}
Program.StatusMessage = "Recharge Successful";
TextFill();
}
}
You should extract
Program.sp.SoundLocation = System.IO.Path
.GetDirectoryName(System.Reflection.Assembly
.GetExecutingAssembly().Location)
+ "/aimlife_success.wav";
Program.sp.Play();
and
RechargeStatus = "Failed";
Program.sp.SoundLocation = System.IO.Path
.GetDirectoryName(System.Reflection.Assembly
.GetExecutingAssembly().Location)
+ "/aimlife_error.wav";
Program.sp.Play();
into its own methods to make this code clearer, looks like a mess.
Could I write the following logic in a simpler, more easy-to-read way? The below does what I need, but it is very messy:
if (IsChanged == true)
{
return;
}
// Executed when the close (x) button is pressed,
// as the Status string is not yet set to a real value...
else if (Status == "" && IsChanged == false)
{
CancelClose();
}
// saving logic falls to here...
else if (IsChanged == false && Status == "saving")
{
IsChanged = false;
}
Thanks
if (isChanged) return;
switch (Status) {
case "":
CancelClose();
break;
case "saving":
// IsChanged = false;
break;
}
This is about as neat as it gets. Note that because you return if isChanged is true you can further on always assume that isChanged is false.
This is a bit cleaner:
if (IsChanged)
{
}
else if (Status == "saving")
{
}
else if (Status == "")
{
}
else
{
}
I would recommend you use an enum to represent the status. This will allow your code to be strongly typed.
public enum Status
{
Closing,
Saving,
Changed,
}
Then you can use a nice switch statement to decide what action to take.
switch (_status)
{
case Status.Saving:
break;
case Status.Closing:
break;
case Status.Changed:
break;
default:
break;
}
if(IsChanged)
return;
if(Status == "saving")
{
// save
}
else if(string.IsNullOrEmpty(Status))
{
CancelClose();
}
Since you return if IsChanged==true, you don't need it in the other ifs.
if (IsChanged == true)
return;
switch (Status)
{
case "":
CancelClose();
break;
case "saving":
break;
}
yes:
if (IsChanged) return;
if (String.IsNullOrEmpty(Status)) CancelClose();
cut the first else if to just if. If IsChanged is true the "else" will never be reached.
remove the IsChanged==false from your other ifs because they are always true.
Think about enums instead of strings for your status.
I'd recommend:
if (IsChanged)
{
return;
}
if (CurrentStatus == Status.None)
{
CancelClose();
return;
}
if (CurrentStatus == Status.Saving)
{
// IsChanged = false;
}
if(!IsChanged) {
if (Status == "saving") // saving logic falls to here...
{
// IsChanged = false;
}
else if (Status == "") // Executed when the close (x) button is pressed, as the Status string is not yet set to a real value...
{
CancelClose();
}
} else {
return;
}
It can be simplifed in to
if (IsChanged)
{
return;
}
else if (Status == "") // Executed when the close (x) button is pressed, as the Status string is not yet set to a real value...
{
CancelClose();
}
else if (Status == "saving") // saving logic falls to here...
{
// IsChanged = false;
}
You do not need the == True in the first check, as it already is true or false. you do not need to check for false in the other choices because if it is not true it must be false.
if (IsChanged) return;
if (Status == "saving")
{
//IsChanged = false;
}
else if (Status = "")
{
CancelClose();
}
I'd avoid beginning your variable names with uppercase.
if (IsChanged)
return;
if (String.IsNullOrEmpty(Status)) // better use this unless you would like a
CancelClose(); // nullPointerException
else if (Status.equals("Saving"))
// whatever you want for save
I'm not familiar with c#, but it supports the conditional operator
condition ? first_expression : second_expression;
Since I'm not familiar with c#, I won't try to re-write your code, but in any case, the ternary operator can lead to pleasing concision in some places.
Here's Eric Lippert's comment from this post:
Now that you know the answer, you can
solve this puzzle: write me a program
in which there is a reachable goto
which goes to an unreachable label. –
Eric Lippert Jul 17 at 7:17
I am not able to create a code which will have reachable goto pointing to an unreachable label. Is that even possible? If yes, what would the C# code look like?
Note: Let's not get into discussion about how 'goto' is bad etc. This is a theoretical exercise.
My original answer:
try
{
goto ILikeCheese;
}
finally
{
throw new InvalidOperationException("You only have cottage cheese.");
}
ILikeCheese:
Console.WriteLine("MMM. Cheese is yummy.");
Here is without the compiler warning.
bool jumping = false;
try
{
if (DateTime.Now < DateTime.MaxValue)
{
jumping = (Environment.NewLine != "\t");
goto ILikeCheese;
}
return;
}
finally
{
if (jumping)
throw new InvalidOperationException("You only have cottage cheese.");
}
ILikeCheese:
Console.WriteLine("MMM. Cheese is yummy.");
By the way if you use goto the csharp compiler for example for this case without finally block changes the code to a version without goto.
using System;
public class InternalTesting
{
public static void Main(string[] args)
{
bool jumping = false;
try
{
if (DateTime.Now < DateTime.MaxValue)
{
jumping = (Environment.NewLine != "\t");
goto ILikeCheese;
}
else{
return;
}
}
finally
{
if (jumping)
{
//throw new InvalidOperationException("You only have cottage cheese.");
Console.WriteLine("Test Me Deeply");
}
}
ILikeCheese:
Console.WriteLine("MMM. Cheese is yummy.");
}
}
Turns To:
public static void Main(string[] args)
{
bool flag = false;
try
{
if (DateTime.Now < DateTime.MaxValue)
{
flag = Environment.NewLine != "\t";
}
else
{
return;
}
}
finally
{
if (flag)
{
Console.WriteLine("Test Me Deeply");
}
}
Console.WriteLine("MMM. Cheese is yummy.");
}
goto cant_reach_me;
try{
cant_reach_me:
}
catch{}
This is either a compile or runtime error, I can not remember. The label must be outside the try/catch block