i am trying to avoid extra lines of code. so i am running this by you guys to see if it correct. i wrote an inline condition to check for 2 elments in an object.
if the Notification Date (EndsAt) is assigned and the errormessage is NullorEmpty or the Notification Date is not assigned and the errormessage is not NullorEmpty then return "09".
if ((Notification.EndsAt.HasValue && String.IsNullOrEmpty(Notification.ErrorMessage)) || (!Notification.EndsAt.HasValue && !String.IsNullOrEmpty(Notification.ErrorMessage)))
{
return "09";
}
thanks for your help.
What exactly is your question?
Are my conditions correct in checking 2 elements?
If you're asking if your conditions are correct and do what you ask them to do, then that looks OK. The parentheses and bangs go where they should.
Is there any way I can reduce the condition checks?
Can't answer that since you didn't mention what you want to return for cases where:
EndsAt is not Assigned & ErrorMessage IS NullorEmpty
EndsAt is assigned & ErrorMessage IS NOT NullorEmpty
Can I improve performance and readability?
Since the conditional logic here depends on whether EndsAt hasValue and if ErrorMessage is null or empty, you could just store them in variables and compare those variables with the boolean logic you supplied. This reduces length of code (and improves readability), and if getting those boolean values multiple times in your program takes awhile, having them as local variables will improve performance. (think about how saving the count of elements in an array and using it multiple times (while it remains unchanged) is more efficient than calling the count method multiple times when you know the count won't change.
Related
This question already has answers here:
"If" statement - Order of validation of objects?
(6 answers)
Closed 2 years ago.
I would like to check each condition and return if true.
Is it better to have:
1. Multiple conditions in a single if statement?
if (string.IsNullOrEmpty(myStr) ||
myBool == true ||
myList.Count == 0)
{
return;
}
2. Or multiple if statements, each checking a different condition.
if (string.IsNullOrEmpty(myStr))
{
return;
}
if (myBool == true)
{
return;
}
if (myList.Count == 0)
{
return;
}
If myStr is Empty.
My thought is that the first way checks all 3 conditions before it reaches the return (or does it)?
And the second way only has to check the 1st condition string.IsNullOrEmpty, reaches the return, and doesn't have to process the other 2 condition checks below it.
Or does the compiler optimize the code to work most efficient no matter how the source is written?
They are equivalent. The || operator short-circuits, so as soon as it reaches a condition that is true, it stops checking other conditions and returns true.
The | operator does not short-circuit, so it would evaluate every operand before returning a value.
Same goes for && and & but with false. As soon as a false condition is reached, the && operator returns false.
So your two methods are functionally identical. Use whichever one you think is the cleanest, easiest to infer intent, etc.
Or does the compiler optimize the code to work most efficient no matter how the source is written?
Well, the optimizer can make changes to code for efficiency, but it cannot change the functional behavior, meaning it won't change the order of the operations. Imagine you had something like:
if ((x == 0) || (y/x > 1))
this is a common way to prevent divide-by-zero errors. If the compiler could rearrange the operands, then it could introduce divide-by-zero errors.
It's a matter of preference really, as both will result in the same overall performance. Both are equivalent to each other. By default, C# uses short-circuit evaluation, meaning the if statement will stop as soon as it finds an expression that evaluates to true. Most of the time, I've seen it written as a single if statement, but separate checks can be easier for debugging if you want to put a breakpoint on one of the specific conditions.
Also of note, although if (myBool == true) will work, you don't have to explicitly equate it to true. The if statement just has to evaluate to true, so you can write it as if (myBool). Again it's personal preference, but it's shorter and can make it easier to read.
Lastly, you might consider using string.IsNullOrWhiteSpace, which is just like string.IsNullOrEmpty but also checks if the string only contains spaces, tabs, etc., with no content.
I have a robot stock trading program that I've been working on for a few months. The other day though I added a 2nd condition to the code that determines when the trade gets exited. Condition as follows:
decimal entryPrice;
decimal CurrentPrice;
decimal openShares;
if ((1st condition) && (((entryPrice - CurrentPrice) * openShares) >= 8))
Today was the first day the situation came up, and I happened to have the day off work so I was observing the trades. The condition didn't trigger though. The trade kept going until I manually exited.
What should have happened is that it would subtract the current price from the price at time of entry, then multiply that by the number of shares to get the current profit. And if it's greater than or equal to 8, it triggers. This particular code was only for exiting short trades, so subtracting the current price from the entry price should return a positive value.
I verified in my code that the entryPrice was being logged at time of purchase. So all I can think is that I'm messing something up with the condition format. Either it doesn't like the bracket arrangement or the resulting number value types aren't compatible with each other. Does anything jump out at you? Thanks.
Not sure about the exact cause, but if your "1st condition" is false, the second condition will not be evaluated at all for many languages.
So please make sure the '1st condition' is true.
After that, if the problem still exist, you can print out some log messages about the variable values to see what's going on.
Change your conditional to
if(true){
//code after the conditional
}
If this executes, Then something isn't getting set properly inside your brackets.
(((entryPrice - CurrentPrice) * openShares) >= 8)
This is your second part of the condition. Parenthesis match up, however, I do not know what's happening inside the conditional. Since you're multiplying, it very easily could be constantly greater than 8. (maybe you meant less than?)
Try printing out some values, and see where that leads you. Print out your first condition, then your second condition.
If you have support for implicit conversions, try using BITWISE AND (&) rather than LOGICAL AND (&&).
This way, the second condition will be 'resolved' to a variable. (i.e. ran)
I have some weird logic stuff going on.
x=false;
This one does not work:
while (R2.TS("a") && R2.TL("b") && (s=R2.SL().Trim()).Length > 0)
{
x=true;
}
result: x=false;
This one does work:
while (R2.TS("a") && R2.TL("b"))
{
if((s=R2.SL().Trim()).Length > 0)
{
x=true;
}
}
result: x=true;
Also, maybe it helps to know that those functions return true only if executed in right order, like R2.TS("a") then R2.TL("b") and then ((s=R2.SL().Trim()).Length > 0).
input is the same, but something is surely wrong here. Any ideas ?
thanks in advance.
Yes, the loops do two different things.
I think you mean a logic error, not a syntax error. Syntax error means it won't compile. Logic error means it doesn't do what you expect.
The first one will terminate if the R2.SL() expression is false. At least the first time round, (s=R2.SL().Trim()).Length > 0 must necessarily be false, so loop 1 terminates and x is never set to true. That is the only way you would get a difference between your two loops, all other conditions being the same.
In loop 2, intermediate values for R2.SL() isn't a problem, provided the other loop conditions remain true. When (s=R2.SL().Trim()).Length > 0 evaluates to true, x will be set.
Use the debugger luke. There is little point us trying to work out why this doesn't give you the result you want. It is better for you to work that out with some help. Click on the first line and push F9. It should turn red. Run your program and it will stop at this line. You can then hover over different variables to see which ones have which values. Then push F11 to step forward through your program.
In the first case have three conditions to which R2 has to comply namely
R2.TS("a") AND R2.TL("b") AND (s=R2.SL().Trim()).Length > 0), before you will enter the loop and return the value of x
In the 2nd case you only have two conditions to which R2 has to comply namely
R2.TS("a") AND R2.TL("b") and after the loop is entered, you have a new condition before the x value is returned.
They probably both work, but in the first case, you don't supply data which complies to the requirements of the loop.
It may be connected with && and || operations. They are shortaned. It means, that operations are looked continuously utill the first false occurs in the condition.
Because of shortaned operations you get 2 different cycles, which have different logics. Use the 2 cycle type. It's more correct.
I am validating input on a form and attempting to prompt the user of improper input(s) based on the combination of controls used.
For example, I have 2 combo boxes and 3 text boxes. The 2 combo boxes must always have a value other than the first (default) value, but one of three, or two of three, or all text boxes can be filled to make the form valid.
In one such scenario I have a 6 line if statement to try to make the test easily readable:
if ((!String.Equals(ComboBoxA.SelectedValue.ToString(), DEFAULT_COMBO_A_CHOICE.ToString())
&& !String.IsNullOrEmpty(TextBoxA.Text)
&& !String.Equals(ComboBoxB.SelectedValue.ToString(), DEFAULT_COMBO_B_CHOICE.ToString()))
||
(!String.IsNullOrEmpty(TextBoxB.Text)
|| !String.IsNullOrEmpty(TextBoxC.Text)))
{
//Do Some Validation
}
I have 2 questions:
Should this type of if statement be avoided at all cost?
Would it be better to enclose this test in another method? (This would be a good choice as this validation will happen in more than one scenario)
Thanks for your input(s)!
In such a case I find it helps to move some of the logic out of the if statement and into some more meaningfully named booleans. Eg.
bool comboBoxASelected = !String.Equals(ComboBoxA.SelectedValue.ToString(), DEFAULT_COMBO_A_CHOICE.ToString());
bool comboBSelected = !String.Equals(ComboBoxB.SelectedValue.ToString(), DEFAULT_COMBO_B_CHOICE.ToString());
bool textBoxAHasContent = !String.IsNullOrEmpty(TextBoxA.Text);
bool textBoxBHasContent = !String.IsNullOrEmpty(TextBoxB.Text);
bool textBoxCHasContent = !String.IsNullOrEmpty(TextBoxC.Text);
bool primaryInformationEntered = comboBoxASelected && textBoxAHasContent && comboBSelected;
bool alternativeInformationEntered = textBoxBHasContent || textBoxCHasContent;
if (primaryInformationEntered || alternativeInformationEntered)
{
//Do Some Validation
}
Obviously, name the combo and text boxes to reflect their actual content. When someone has to work their way through the logic several months down the line they'll thank you.
a) Doesn't have to necesarily be avoided at all costs. The code works. But it is certainly messy, confusing and I would say could be difficult to maintain.
b) Yes. Give it a relevant name so that the code reader knows what is going on there.
I personally wouldn't have a big issue with code like this. (Your last set of parentheses seem unnecessary.)
Generally, I'd like to keep my if statements simpler. But all your conditions are simple ones. If you really need to test that many tests, then I'd keep it like it is.
It is not very readable yes. But you can shorten it:
!String.Equals(ComboBoxA.SelectedValue.ToString(), DEFAULT_COMBO_A_CHOICE.ToString()
could also be written as:
ComboBoxA.SelectedValue.ToString()!=DEFAULT_COMBO_A_CHOICE
I presume DEFAULT_COMBO_A_CHOICE is already of string to ToString si superflous.
also the parenthese around
(!String.IsNullOrEmpty(TextBoxB.Text)
|| !String.IsNullOrEmpty(TextBoxC.Text))
are not necessary.
IMO such conditions should be avoided (though not at all costs). They are very difficult to read an maintain.
There are several ways of doing that
Try and group the conditions according to the behavior they represent. For example
if (OrderDetailsSelected() && ShippingAddressProvided() )
{
This way you can also avoid the duplication of the conditions within your form.
Secondly, you can use the Boolean Algebra to simplify the expression and
Use Extract Method refactoring to move conditions, which are difficult to read in functions to avoid duplication and make them more readable.
For ex. The condition
String.Equals(ComboBoxB.SelectedValue.ToString(), DEFAULT_COMBO_B_CHOICE.ToString())
can be extracted into a function
private bool IsDefaultA() { return ... }
Is there a better way for writing a condition with a large number of AND checks than a large IF statement in terms of code clarity?
Eg I currently need to make a field on screen mandatory if other fields do not meet certain requirements. At the moment I have an IF statement which runs over 30 LOC, and this just doesn't seem right.
if(!(field1 == field2 &&
field3 == field4 &&
field5 == field6 &&
.
.
.
field100 == field101))
{
// Perform operations
}
Is the solution simply to break these down into smaller chunks and assign the results to a smaller number of boolean variables? What is the best way for making the code more readable?
Thanks
I would consider building up rules, in predicate form:
bool FieldIsValid() { // condition }
bool SomethingElseHappened() { // condition }
// etc
Then, I would create myself a list of these predicates:
IList<Func<bool>> validConditions = new List<Func<bool>> {
FieldIsValid,
SomethingElseHappend,
// etc
};
Finally, I would write the condition to bring forward the conditions:
if(validConditions.All(c => c())
{
// Perform operations
}
The right approach will vary depending upon details you haven't provided. If the items to be compared can be selected by some sort of index (a numeric counter, list of field identifiers, etc.) you are probably best off doing that. For example, something like:
Ok = True
For Each fld as KeyValuePair(Of Control, String) in CheckFields
If fld.FormField.Text fld.RequiredValue Then
OK = False
Exit For
End If
Next
Constructing the list of controls and strings may be a slight nuisance, but there are reasonable ways of doing it.
Personally, I feel that breaking this into chunks will just make the overall statement less clear. It's going to make the code longer, not more concise.
I would probably refactor this check into a method on the class, so you can reuse it as needed, and test it in a single place. However, I'd most likely leave the check written as you have it - one if statement with lots of conditions, one per line.
You could refactor your conditional into a separate function, and also use De Morgan's Laws to simplify your logic slightly.
Also - are your variables really all called fieldN?
Part of the problem is you are mixing meta data and logic.
WHICH Questions are required(/must be equal/min length/etc) is meta data.
Verifying that each field meets it's requirements is program logic.
The list of requirements (and the fields that apply too) should all be stored somewhere else, not inside of a large if statement.
Then your verification logic reads the list, loops through it, and keeps a running total. If ANY field fails, you need to alert the user.
It may be useful to begin using the Workflow Engine for C#. It was specifically designed to help graphically lay out these sorts of complex decision algorithms.
Windows WorkFlow Foundation
The first thing I'd change for legibility is to remove the almost hidden negation by inverting the statement (by using De Morgan's Laws):
if ( field1 != field2 || field3 != field4 .... etc )
{
// Perform operations
}
Although using a series of && rather than || does have some slight performance improvement, I feel the lack of readability with the original code is worth the change.
If performance were an issue, you could break the statements into a series of if-statements, but that's getting to be a mess by then!
Is there some other relationship between all the variables you're comparing which you can exploit?
For example, are they all the members of two classes?
If so, and provided your performance requirements don't preclude this, you can scrape references to them all into a List or array, and then compare them in a loop. Sometimes you can do this at object construction, rather than for every comparison.
It seems to me that the real problem is somewhere else in the architecture rather than in the if() statement - of course, that doesn't mean it can easily be fixed, I appreciate that.
Isn't this what arrays are basically for?
Instead of having 100 variables named fieldn, create an array of 100 values.
Then you can have a function to loop combinations in the array and return true or false if the condition matches.