if (a or b) and c statement - c#

I'm having difficulty with a multiple option if statement.
Version 1 matches all without considering the && .contains("up")
if (
|| drow["ifName"].ToString().ToLower().Contains("vlan")
|| drow["ifName"].ToString().ToLower().Contains("st0")
|| drow["ifName"].ToString().ToLower().Contains("ge-0")
&& drow["ifStatus"].ToString().ToLower().Contains("up")
)
Version 2 matches none.
if ( (
|| drow["ifName"].ToString().ToLower().Contains("vlan")
|| drow["ifName"].ToString().ToLower().Contains("st0")
|| drow["ifName"].ToString().ToLower().Contains("ge-0")
)
&& drow["ifStatus"].ToString().ToLower().Contains("up")
Something I am missing?
Table looks basically like
ifName | ifStatus
vlan.0 | up
st0.1 | up
pp0.0 | up
ge-0/0/0 | down
EDIT:
So the goal is to match only rows that have ifStatus = UP, also changed table to clarify a real example.

What is your intended parse? logical OR (||) and logical AND (&&) are both left-associative and have different operator precedences:
http://msdn.microsoft.com/en-us/library/aa691323(v=vs.71).aspx
Logical AND binds more tightly than does logical OR, so, an expression like
A || B || C && D
parses as if it were written
A || B || ( C && D )
If that is your intent, you're good. If not, you'll need to add parentheses as needed to get the desired parse. My suspicion is that your intended parse is more like:
(A || B || C ) && D
But that is not how your original test parses.
As a good general rule, if you're mixing ANDs and ORs in a logical expression, always use parentheses to indicate your intent. Misunderstanding operator precedence in logical expressions is a major source of bugs.

This may not fix your problem, but it should make it easier to see what you're doing, as well as make the list more maintainable:
var matchNames = new[] {"a", "b", "c", "vlan.10"};
if (drow["ifStatus"].ToString().ToLower().Contains("up") //check up first, because it's cheaper
&& matchNames.Any(m => drow["ifName"].ToString().ToLower().Contains(m) )
{
//...
}

You can use linq to do this, for sample, add this namespace:
using System.Linq;
and try this:
string[] items = new[] { "vlan.10", "a", "b", "c" };
if (drop["IfStatus"].ToString().IndexIf("up", StringComparison.OrdinalIgnoreCase) > -1 &&
items.Any(x => drop["IfName"].ToString().IndexOf(x, StringComparison.OrdinalIgnoreCase) > -1)
{
// true...
}
Read about the Turkey Test, it shows why is important using the IgnoreCase method to compare instead Contains.

Using a regex here can simplify the logic.
if((Regex.IsMatch(drow["ifName"].ToString().ToLower(), "[abc]"))
&& (Regex.IsMatch(drow["ifStatus"].ToString().ToLower(), "up")))
{
}

in first case: it produce true if any one of the expression (OR Expression or AND Expression)evaluates to true.
Note : it is similar to if(A || B || C || D && E)
so if any OR Expressionin (A,B,C) evalutes to true or Expression D and E evaluates to true it becomes true.
in second case : it produce true if any one of the OR expressions is true and AND Expression drow["ifStatus"].ToString().ToLower().Contains("up") also must be true as you are using parenthesis pair.
Note : it is similar to if( (A || B || C || D) && (E) )
so if any one of the OR Expression(A,B,C,D) should evaluate to true and also AND expression E must be true to produce the result true.
Try This:
String name=drow["ifName"].ToString().ToLower();
Sting status=drow["ifStatus"].ToString().ToLower();
if ( (name.Contains("vlan.10") || name.Contains("a") || name.Contains("b")
|| name.Contains("c")) && (status.Contains("up")))

Related

Regex to validate logical && || operators in string

I am trying to create a Regex expression to validate logical && || string combonation and its corresponding opening and closing () brackets.
I have been messing with the Regex hieroglyphic pattern but can't seem to get it working correctly, mainly due to my complete lack of understanding of the Regex pattern.
After several hours of StackOverflow and google this is what I have so far, I feel I am close.
private void ValidationTest()
{
string hieroglyphics = #"^(?=^[^()]*\((?>[^()]+|\((?<DEPTH>)|\)(?<-DEPTH>))*(?(DEPTH)(?!))\)[^()]*$)[(]*\d+[)]*(\s+(&&|\|\|)\s+[(]*\d+[)]*)*$";
var tests = new List<string>
{
// Working
"(1 && 2)",
"((1 && 2) && (3 || 4))",
"((1 && 2) && (3 || 4) || ((1 && 2) && (3 || 4)))",
// Not working
"(Stack && Overflow)"
};
if (tests.All(test => Regex.IsMatch(test, hieroglyphics)))
{
MessageBox.Show("Woohoo!!");
}
}
So the main issue with what I have so far is if ther are no brackets 1 && 2 it wont validate, same with (1 && 2) && (3 || 4).
Also it seems to ignore words alltogeter (Stack && Overflow)
Examples of some strings I am tring to validate.
"IsRecording && IsPlaying"
"IsVisible && (IsPlaying && (IsMusic || IsRadio))"
There is also some keywords that contain brakets that could mess things up
Example:
"IsWindowVisible(2) && (IsControlVisible(22) && IsControlFocused(100))"
Edit:
As it is now this expression works fine validating the kind of complexity I need, however the only real issue I have is that its nubers only.
Complex example that validates fine with this Regex
"((1 && 2) && (3 || 4) || ((1 && 2) && (3 || 4)))"
A simple string 1 && 2 wont validate without brakets, but I dont mind adding brackest to these.
all I need is to add support for words instead of just numbers, this will be a fixed list of words if that helps.
If someone can spot the error or point me in a better direction would be awesome
Thanks
Edit:
Answer by mellamokb worked perfect. It seems the trouble was the d+ needed to be 0-9a-zA-Z()
Here is the pattern incase it usefull for anyone else.
string hieroglyphics = #"^(?=^[^()]*(?>[^()]+|\((?<DEPTH>)|\)(?<-DEPTH>))*(?(DEPTH)(?!))[^()]*$)[(]*[0-9a-zA-Z()]+[)]*(\s+(&&|\|\|)\s+[(]*[0-9a-zA-Z()]+[)]*)*$";
it validates exactly what I need
Examples:
"IsPlayer(Video) && Player(Playing)",
"((IsPlayer(Video) && (Player(Playing) && ControlIsVisible(34))) || (IsPlayer(Video) && (Player(Playing) && ControlIsVisible(34)))) && ControlIsFocused(22)"
I think the reason you are not able to validate expressions without a wrapping () is the wrapping parentheses in your core nesting logic. If you take out the following parentheses I note below, then the other two non-wrapped expressions validate:
^(?=^[^()]*\((?>[^()]+|\((?<DEPTH>)|\)(?<-DEPTH>))*(?(DEPTH)(?!))\)[^()]*$...
^^ remove this remove this ^^
Then in order to allow expressions that are not just numerical, you need to replace your restrictive \d with a more liberal definition of what you want to validate, say, [0-9a-zA-Z]:
...[(]*\d+[)]*(\s+(&&|\|\|)\s+[(]*\d+[)]*)*$
^^ change these expression ^^
So it would become:
...[(]*[0-9a-zA-Z]+[)]*(\s+(&&|\|\|)\s+[(]*[0-9a-zA-Z]+[)]*)*$
Demo: http://ideone.com/jwkcpL

If statement clarification of AND/OR

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

Validating a Radio Box

I'm simply trying to check that one of the three radio boxes has been checked, for some reason even when in debug console all boxes '.Selected = false' it is still skipping over my error message. Any help is appreciated.
if ((rdoIndoor.Checked = false ) && ( rdoOut.Checked = false ) && ( rdoSwimming.Checked = false ))
{
MessageBox.Show("Please select an event style");
}
You are using an assignment operator instead of a comparison operator. The = operator is for assignment. Use == for comparison.
Better yet, get rid of your == operator altogether, and use the ! operator, like this:
if ( !rdoIndoor.Checked && !rdoOut.Checked && !rdoSwimming.Checked )
{
MessageBox.Show( "Please select an event style" );
}
The equality operator, used to compare values, is ==
So your code should be:
if ((rdoIndoor.Checked == false ) &&
( rdoOut.Checked == false ) &&
( rdoSwimming.Checked == false ))
......
use double equals signs (rdoIndoor.Checked **==** false) etc
Single '=' means assignment, i. e. from now let 'rdoIndoor.Checked' be false.
Double '==' is logical test.
You probably know that ;)

Does .net stop checking the rest of an IF statement if you use an and/or ( || / && )?

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.

Concat string in IsNullOrEmpty parameter

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.

Categories

Resources