I would like to re-order sub expressions in an if statement. Here is an example:
Input:
if ((a == 1) || (a == 3) || (a == 2))
{
}
Desired output:
if ((a == 1) || (a == 2) || (a == 3))
{
}
Is there any tool that can automatically reorder these sub expressions?
Or the following identical code:
Input:
switch (a)
{
case: 1;
case: 3:
case: 2;
break;
}
Desired output:
switch (a)
{
case: 1;
case: 2:
case: 3;
break;
}
Clarification:
My question does not address short circuiting. This is a useful discussion, and as Reed pointed out re-ordering parameters in most cases is dangerous.
I was just curious if parsing tools such as ReSharper or Code Rush have this functionality. These tools probably create an AST to preform their refactoring and for them to reorder sub-expressions would not be too difficult.
I don't know of a tool that would automatically do this, at least in the "if" statement case.
In general, it would be bad if a tool did this automatically. The following two statements behave differently:
if ((a == 1) && (b == 3) && (c == 2))
and
if ((a == 1) && (c == 2) && (b == 3))
In the first case, if b != 3, but a == 1, it will check a, then check b, then skip the block.
In the second case, it would check a, then check c, then check b. You'd lose the ability to short-circuit the checks.
Granted, in most cases, this doesn't matter, but when you're using methods instead of values for a/b/c, it can be expensive.
Edit: I see that you've updated to use OR instead of AND. The same issue exists with OR, except that the short circuit will happen when the first condition is true, instead of when the first condition is false.
I agree with Reed Copsey's answer. However, since no one has mentioned it yet:
Depending on the language that you use, the switch statement doesn't behave the same as if/elsif/else. I know that for C, Java, etc. they use branch tables to determine what should be executed. (Not sure about something like PHP.) It's mentioned on the Wikipedia article, if you'd like to read more.
Related
This question already has answers here:
Control cannot fall through from one case label
(8 answers)
Closed 9 years ago.
I am trying to convert an if statement to switch cases (for readability)
1) I've read switch statements are aweful in general - Is that true?
https://stackoverflow.com/questions/6097513/switch-statement-inside-a-switch-statement-c
2) The statement goes like this:
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
case Display.NonExpense:
if (expected.EXPENSE == true)
break;
case Display.All:
//Code
break;
}
Error is:
Control cannot fall through from one case label ('case 1:') to another
This is the original if statement:
if ((Show == Display.All) || (expected.EXPENSE == true && Show == Display.Expense) || (expected.EXPENSE == false && Show == Display.NonExpense))
{
//Code
}
First off, I notice that you forgot to ask a question in your second point. So I'm going to ask some questions for you addressing your second point:
What is the meaning of the "can't fall through" error?
Unlike C and C++, C# does not allow accidental fall-through from one switch section to another. Every switch section must have an "unreachable end point"; it should end with a break, goto, return, throw or (rarely) infinite loop.
This prevents the common bug of forgetting to put in the break and "falling through" accidentally.
You've written your code as though fall-through is legal; my guess is that you're a C programmer.
How can I force fall-through in C#?
Like this:
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
else
goto case Display.All;
case Display.NonExpense:
if (expected.EXPENSE == true)
break;
else
goto case Display.All;
case Display.All:
//Code
break;
}
Now the reachability analyzer can determine that no matter which branch of the "if" is taken, the switch section endpoint is unreachable.
Is this good style?
No. Your original code was a lot more readable.
I've read switch statements are aweful in general - Is that true?
Opinions vary. Switch statements are very useful when there is a small number of very "crisp" alternatives whose behaviours do not interact in complex ways. Some people will tell you that switched logic should instead be handled by virtual methods or visitor patterns, but that can be abused as well.
Should I use a switch in this particular case?
I wouldn't.
How would you improve my code?
if ((Show == Display.All) ||
(expected.EXPENSE == true && Show == Display.Expense) ||
(expected.EXPENSE == false && Show == Display.NonExpense))
{
//Code
}
First off, don't name things IN ALL CAPS in C#.
Second, don't compare Booleans to true and false. They're already Booleans! If you want to know the truth of statement X you would not say in English "is it true that X is true?" You would say "Is X true?"
I would likely write:
if (Show == Display.All ||
Show == Display.Expense && expected.Expense ||
Show == Display.NonExpense && !expected.Expense)
{
//Code
}
Or, even better, I would abstract the test away into a method of its own:
if (canDisplayExpenses())
{
//Code
}
Or abstract the whole thing away:
DisplayExpenses();
The compiler will not understand what you mean here.
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
// missing break here
case Display.NonExpense:
The compiler will not connect the dots and understand that the break; statement inside your if statement is linked to the switch statement. Instead it will try to link it to a loop, since break; statements on their own can only be used with loops, to break out of it.
That means that your case block is missing its break statement to complete it, and thus the compiler complains.
Instead of trying to wring the necessary code out of a switch statement, I would instead break up your original if statement.
This is yours:
if ((Show == Display.All) || (expected.EXPENSE == true && Show == Display.Expense) || (expected.EXPENSE == false && Show == Display.NonExpense))
{
//Code
}
This is how I would write it:
bool doDisplayExpected =
(Show == Display.All)
|| (Show == Display.Expense && expected.EXPENSE)
|| (Show == Display.NonExpense && !expected.EXPENSE);
if (doDisplayExpected)
{
// code
}
You don't have to pack everything on one line.
Also, I would try to name properties so that they're easier to read, I would rename the EXPENSE property to IsExpense so that the above code would read like this:
bool doDisplayExpected =
(Show == Display.All)
|| (Show == Display.Expense && expected.IsExpense)
|| (Show == Display.NonExpense && !expected.IsExpense);
if (doDisplayExpected)
{
// code
}
Then, ideally, I would refactor out the sub-expressions to methods:
bool doDisplayExpected =
ShowAll()
|| ShowExpense(expected)
|| ShowNonExpense(expected);
if (doDisplayExpected)
{
// code
}
public bool ShowAll()
{
return Show == Display.All;
}
public bool ShowExpense(Expected expected)
{
return Show == Display.Expense && expected.EXPENSE;
}
public bool ShowNonExpense(Expected expected)
{
return Show == Display.NonExpense && !expected.EXPENSE;
}
Then you can put the expression back into the if-statement:
if (ShowAll() || ShowExpense(expected) || ShowNonExpense(expected))
{
// code
}
This should be easier to read, and change later on.
Use if statements and extract complex conditions into methods, e.g
if (ShowAll() || ShowExpense())
{
}
Remember about OOP and polymorphism every time you write such 'switch', adding another
case to that code will be a nightmare
see this and similar (C++) instructions about converting switches
P.S if you are interested in making your code clean and readable, consider reading Smalltalk Best Practice Patterns by Kent Beck and/or Clean Code by Uncle Bob
I really enjoyed both of them, highly recommend.
If you want readability, just throw away your syntax trash:
if (Show == Display.All || expected.EXPENSE && Show == Display.Expense || !expected.EXPENSE && Show == Display.NonExpense)
{
//Code
}
Provide the else part for each of them so it will not throw error, however as others say, you actually don't need switch in this case.
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
// do what you want
break;
else
// do what you want
break;
case Display.NonExpense:
if (expected.EXPENSE == true)
// do what you want
break;
else
// do what you want
break;
case Display.All:
//Code
break;
}
The reason why you get this error is that you are not defining break statements.
You defined the break conditionally.
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
// Note that the break above is in scope of you if statement, and will
// result in a compiler error
case Display.NonExpense:
...
}
Either make sure every case statement has its own break or group the case statements as follows.
switch (Show)
{
case Display.Expense:
case Display.All:
// do stuff
// Expense and All have the same behavior
}
Refactor out the if statements so you can express it like so:
if (isDisplayAll() || isExpense(expected) || isNonExpense(expected))
{
// Code
}
The extracted logic:
private bool isDisplayAll()
{
return (Show == Display.All);
}
private bool IsExpense(Expected expected)
{
return expected.EXPENSE && (Show == Display.Expense);
}
private bool IsNonExpense(Expected expected)
{
return !expected.EXPENSE && (Show == Display.NonExpense);
}
Agree with Dennis, you don't want a switch case for this problem.
Although probably less readable, you can also use shorter:
if (Show == Display.All || (expected.EXPENSE == (Show == Display.Expense)))
{
//Code
}
I'm sorry to ask such an easy question.. I just need some clarifications, because sometimes I mix the differences up.
Can somebody please help me by explaining the difference between the following if statements?
sending = true;
if (sending && e.AssetType == AssetType.Notecard) //#1
vs.
if ((sending) && (e.AssetType == AssetType.Notecard)) //#2
vs.
if (sending || e.AssetType == AssetType.Notecard) //#3
vs.
if ((sending) || (e.AssetType == AssetType.Notecard)) //#4
In this specific case, I need it to evaluate to something like:
"If(sending == true AND e.AssetType == AssetType.Notecard)"
In an other case I need the if statement to check one string and contents of a list like:
"If(string == "Name" OR List.Contains("string"))
The first and the second statements are the same (parenthesis are not obligatory in this case, because of C# evaluation priorities!)
if (sending && e.AssetType == AssetType.Notecard)
if ((sending) && (e.AssetType == AssetType.Notecard))
just as:
if ((sending == true) && e.AssetType == AssetType.Notecard))
if ((sending) && (e.AssetType == AssetType.Notecard))
Also the 3° and the 4° statement will give the same result, for the same reason mentioned above: http://msdn.microsoft.com/en-us/library/6a71f45d.aspx
I would use these statements:
if (sending && (e.AssetType == AssetType.Notecard))
and:
if ((string == "Name") || List.Contains("string"))
(but please take care of string comparison modes, such as upper/lower cases and cultures:
String.Compare(string, "Name", StringComparison.CurrentCultureIgnoreCase) == 0
compares strings without regard of the case and with the current culture)
There is no any difference in those codes.
if ((sending) && (e.AssetType == AssetType.Notecard)) and if (sending && e.AssetType == AssetType.Notecard) evaluates into the same thing.
if(sending == true) or if(sending) is the same thing too.
If you're asking about difference between || and &&:
|| is a LOGICAL-OR. It's enough that only one condition would be TRUE to pass if
&& is a LOGICAL-AND. All conditions must be TRUE in order to pass if
In both cases the evaluation will be done from the left to right.
Example of sequence:
if ((sending) && (e.AssetType == AssetType.Notecard)) => if sending==true AND ..rest..
For the first and second statements produce the same result and for the third and fourth statements also produce the same result.
A couple of things to clarify:
In this case, parentheses are not required and it is just extra code.
When you use Logical-AND operation, the first part is always evaluated, and the second part will only be evaluated if the first part is true.
When you use Logical-OR operation, both parts are always evaluated.
When you have more than +2 expressions, then use parentheses to clarify your intentions. e.g. if(A && B || C) is the same as if((A && B) || C) because the Operators Precedence. but if you want the logical-OR operation to be execute first, then you must use parentheses to override the precedence if(A && (B || C))
Furthermore, if(A && B == C) is the same as if(A && (B == C)) because Equality operation has higher precedence than logical-AND
say you have something like:
int num = 0
then you do
if(num > 5 || num < 4)
{
...
}
it checks both, but what if you do
if(num < 4 || num > 5)
{
...
}
does it only check the 1st statement?
same as:
if(num > 5 && num == 0)
{
...
}
it should stop after failing the 1st and... right?
This is called boolean short-circuit evaluation and (although [citation-needed]) yes, C# and VB.NET have it (thanks #Lasse for the correction).
In C#, || and && are the short-circuited versions of | and &, respectively
.
Yes, this feature is called short circuit evaluation. If the first argument to the AND operator (&&) is false, then the entire expression will be false. Similarly with OR (||) if the first operand in true, the entire thing is true.
This feature is useful if you want to write the code similar to:
if(a != null && a.isValid())
... Code ...
This way you are not going to get an exception if a is null.
MSDN documentation http://msdn.microsoft.com/en-us/library/2a723cdk%28v=vs.71%29.aspx
If you do it right, yes. Take a look here: http://devpinoy.org/blogs/nocampo/archive/2007/09/28/short-circuit-evaluation-in-c-and-vb-net.aspx
EDIT: To clarify; C# yes, VB.NET if you use the right keywords.
How to write following statement in c using switch statement in c
int i = 10;
int j = 20;
if (i == 10 && j == 20)
{
Mymethod();
}
else if (i == 100 && j == 200)
{
Yourmethod();
}
else if (i == 1000 || j == 2000) // OR
{
Anymethod();
}
EDIT:
I have changed the last case from 'and' to 'or' later. So I appologise from people who answered my question before this edit.
This scenario is for example, I just wanted to know that is it possible or not. I have google this and found it is not possible but I trust gurus on stackoverflow more.
Thanks
You're pressing for answers that will unnaturally force this code into a switch - that's not the right approach in C, C++ or C# for the problem you've described. Live with the if statements, as using a switch in this instance leads to less readable code and the possibility that a slip-up will introduce a bug.
There are languages that will evaluate a switch statement syntax similar to a sequence of if statements, but C, C++, and C# aren't among them.
After Jon Skeet's comment that it can be "interesting to try to make it work", I'm going to go against my initial judgment and play along because it's certainly true that one can learn by trying alternatives to see where they work and where they don't work. Hopefully I won't end up muddling things more than I should...
The targets for a switch statement in the languages under consideration need to be constants - they aren't expressions that are evaluated at runtime. However, you can potentially get a behavior similar to what you're looking for if you can map the conditions that you want to have as switch targets to a hash function that will produce a perfect hash the matches up to the conditions. If that can be done, you can call the hash function and switch on the value it produces.
The C# compiler does something similar to this automatically for you when you want to switch on a string value. In C, I've manually done something similar when I want to switch on a string. I place the target strings in a table along with enumerations that are used to identify the strings, and I switch on the enum:
char* cmdString = "copystuff"; // a string with a command identifier,
// maybe obtained from console input
StrLookupValueStruct CmdStringTable[] = {
{ "liststuff", CMD_LIST },
{ "docalcs", CMD_CALC },
{ "copystuff", CMD_COPY },
{ "delete", CMD_DELETE },
{ NULL, CMD_UNKNOWN },
};
int cmdId = strLookupValue( cmdString, CmdStringTable); // transform the string
// into an enum
switch (cmdId) {
case CMD_LIST:
doList();
break;
case CMD_CALC:
doCalc();
break;
case CMD_COPY:
doCopy();
break;
// etc...
}
Instead of having to use a sequence of if statements:
if (strcmp( cmdString, "liststuff") == 0) {
doList();
}
else if (strcmp( cmdString, "docalcs") == 0) {
doCalc();
}
else if (strcmp( cmdString, "copystuff") == 0) {
doCopy();
}
// etc....
As an aside, for the string to function mapping here I personally find the table lookup/switch statement combination to be a bit more readable, but I imagine there are people who might prefer the more direct approach of the if sequence.
The set of expressions you have in your question don't look particularly simple to transform into a hash - your hash function would almost certainly end up being a sequence of if statements - you would have basically just moved the construct somewhere else. Jon Skeet's original answer was essentially to turn your expressions into a hash, but when the or operation got thrown into the mix of one of the tests, the hash function broke down.
In general you can't. What you are doing already is fine, although you might want to add an else clause at the end to catch unexpected inputs.
In your specific example it seems that j is often twice the value of i. If that is a general rule you could try to take advantage of that by doing something like this instead:
if (i * 2 == j) /* Watch out for overflow here if i could be large! */
{
switch (i)
{
case 10:
// ...
break;
case 100:
// ...
break;
// ...
}
}
(Removed original answer: I'd missed the fact that the condition was an "OR" rather than an "AND". EDIT: Ah, because apparently it wasn't to start with.)
You could still theoretically use something like my original code (combining two 32-bit integers into one 64-bit integer and switching on that), although there would be 2^33 case statements covering the last condition. I doubt that any compiler would actually make it through such code :)
But basically, no: use the if/else structure instead.
I was looking at a piece of code I wrote in C#:
if(string.IsNullOrEmpty(param1) && string.IsNullOrEmpty(param2) && string.IsNullOrEmpty(param3))
{
// do stuff
}
and decided to make it more readable/concise
if(string.IsNullOrEmpty(param1+param2+param3))
{
// do stuff
}
But looking at it I can't help but cringe. What are your thoughts on this? Have you ever done something like this and do you use it whenever applicable.
Note: The code previous to this line would manipulate a collection by adding specific items depending on if the a param (param1,param2,param3) is NOT empty. This if statement is meant for validation/error handeling.
Personally I prefer the former over the latter. To me the intent is more explicit -- checking if all parameters are null/empty.
The second also hides the fact it does handle nulls. Null strings are odd. Jason Williams above, for example, didn't relise that it does in fact work.
Maybe write it something like this, which is a bit more readable:
bool paramsAreInvalid =
string.IsNullOrEmpty(param1)
&& string.IsNullOrEmpty(param2)
&& string.IsNullOrEmpty(param3);
if (paramsAreInvalid)
{
// do stuff
}
It's a small thing, but I think a minor reformatting of your original results in improved readability and makes the intent of the code about as crystal clear as can be:
if ( string.IsNullOrEmpty(param1) &&
string.IsNullOrEmpty(param2) &&
string.IsNullOrEmpty(param3) )
{
// do stuff
}
Consider this similar set of examples:
if ( c == 's' || c == 'o' || c == 'm' || c == 'e' || c == 't' || c == 'h' || c == 'i' || c == 'n' || c == 'g') {
// ...
}
if ( c == 's' ||
c == 'o' ||
c == 'm' ||
c == 'e' ||
c == 't' ||
c == 'h' ||
c == 'i' ||
c == 'n' ||
c == 'g') {
// ...
}
That won't work. If any of the strings are null, you'll get a null dereference exception. You need to check them before you use them.
In addition, it's very inefficient. You are concatenating all the strings into a new string, then test if this is non-empty. This results in one or more memory allocations and potentially a lot of data being copied, only to be immediately thrown away and garbage collected a moment later.
A better approach is to write a method that takes variable arguments or a list of strings and checks them one by one using IsNullOrEmpty in a loop. This will be more efficient, safe, but still achieve the desired result of tidy code in your if statement.
If you can get the params in a collection (which if it's function you can with the params keyword) then this might work:
if (myParams.Any(IsNullOrTrimEmpty)
{
// do stuff
}
The example uses this string extension and myParams is a string[].
The original code, though longer, is more clear in its intent, and likely similar performance-wise. I'd leave it alone.