Can this statement ever evaluate to FALSE? - c#

I stumbled upon this while doing a review and the author is not available:
int n = Convert.ToInt32(text);
if (((n > 0) || (n < 0)) || (n == 0))
{
return 1;
}
The code in general looks solid and it's hard for me to believe that the only purpose of this snippet is to confuse reviewers, but I don't see a way for this condition to fail. Am I missing something?

This may be a remnant of a nullable type. See here at msdn for an explanation, but basically if your code was originally this:
int? n = StringToInt(text); // People roll their own functions to do this, though
// they really shouldn't
if (((n > 0) || (n < 0)) || (n == 0))
{
return 1;
}
Then this could possibly fall through. Each of the statements above would be false, as n could be null from the function, assuming it returned null on a bad input, and the code supported nullable types.
Unlikely, but when looking at "maintained code" anything is possible. But as written, it MUST return 1 (or throw an exception, as mentioned by others in this thread).

It will always return true, assuming it gets there.
Consider:
bool x = (n > 0) || (n < 0);
bool y = (n == 0);
if (x || y)
{
return 1;
}
If n is not zero then either n > 0 or n < 0 is true, so x is true and y is false.
If n is zero, n == 0 is true, so x is false and y is true.
Either way, one side of the OR is true.

That sure looks like a 100% true statement to me. All those parentheses shouldn't matter in the least, since || is associative, i.e.,
(a || b) || c == a || (b || c) == a || b || c

If you overload the relational operators for your class, it might be the case that the condition evaluates to false, but since n is an int, it always evaluates to true

It's possible that int n = Convert.ToInt32(text); could throw an exception, in which case the if statement never even gets evaluated.
See Convert.ToInt32() on MSDN.

As above, it will always be true because, by definition, any real number is either zero, less than zero or greater than zero, and you have covered all cases in your code.

Always will be 1, unless Convert.ToInt32(text) throws an exception.

I don't see how it can evaluate to false.
If, however, n was declared at a different scope where more than a single thread had access to it and one of these threads changes its value, theres quite a high chance the condition would fail.

it will always be true as you write all the states it might be (e.g < > ==)

Yes, it could also throw an exception if the conversion fails :-)

Related

While statement with multiple conditions

I have the following while statement -
while ((!testString.Contains("hello")) && (NewCount != OldCount) && (attemptCount < 100))
{
//do stuff (steps out too early)
}
This is stepping out of the statement even though all the conditions have not been met.
I have tried to reduce it like -
while (!testString.Contains("hello"))
{
// this works and steps out when it should
}
And this steps out when hello is present for example. I also tried changing this to an OR statement which reversed the problem to never stepping out the statement.
Addint the && (NewCount != OldCount) && (attemptCount < 100)) conditions is causing this behaviour how can I resolve this?
This is stepping out of the statement even though all the conditions
have not been met.
To achieve that you need to specify logical OR (||).
For example:
while ((!testString.Contains("hello")) || (NewCount != OldCount) || (attemptCount < 100))
{
//while at least one those conditions is true, loop will work
}
Which means that inside loop you need to introduce security checks, where required, for conditions which are not more true, while loop is still executing.
As an addition to TigranĀ“s answer. Often (in order to avoid mess with the complex condition) it could be useful to push the condition into the loop:
while (true) { // loop forever unless:
if (testString.Contains("hello")) // ...test string contains "hello"
break;
if (NewCount == OldCount) // ...counts are equal
break;
if (attemptCount >= 100) // ... too many attempts
break;
// ...it's easy to add conditions (as well as comment them out) when you have them
// Loop body
}

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.

Using return and short-hand if in C#

Why wouldn't the following line of code work in a method?
return (count > 0) ? true : false;
It works perfectly fine if I do:
bool ret = (count > 0) ? true : false;
return ret;
Bonus Question: Is it really faster or more effective than the standard if statement?
bool ret = false;
if(count > 0)
ret = true;
return ret;
Which one would you recommend?
I would recommend:
return count > 0;
There's no need to explicitly return true or false.
Having said that, your compilation error intrigues me. At first sight it looks like it should work. Could you post a short but complete example that fails to compile? The type of that conditional expression should be bool with no problems. My guess is you've got a more complicated scenario, and by simplifying the example you've removed the real problem.
As for the bonus question: I don't know which would be faster, nor do I care in 99.99% of cases. I'd be amazed to find that it caused any significant delay, unless it prohibited inlining for some reason. Go for the most readable solution - which is the simple return statement, IMO.
try this:
return count > 0;
before return returns the expression count > 0 is evaluated and gives true or false.
this should also work:
return (count > 0 ? true : false);
but I'd recommend you didn't do this.
I always try to keep the amount of horizontal operations low, I believe it makes it easier to read code.
just imagine the following scenario which will just confuse :)
return count > 0 ? false : true;
From the point of view of C#
return count > 0;
is better for it's readabilty.
But the compiler optmize the code, so your three options are actually the same once compiled. You could try to look at the IL code to verify!
this works
return (count > 0 ? true : false);
You can then make it return other values than true and false. In your particular case I would do like the other suggestions; return count > 0;

How to check if two string are of the same length?

I want to check if two string are of the same length. I tried the following, but it doesn't work.
string passnew = "1233";
string passcnfrm = "1234";
if((passnew.Length&&passcnfrm.Length)>6 ||(passnew.Length&&passcnfrm.Length)<15)
{
// ...
}
Why does it not work? What do I need to change?
if(passnew.Length == passcnfrm.Length &&
passnew.Length > 6 && passnew.Length < 15)
{
// do stuff
}
You are missing some basic syntax lessons. What you write inside of these brackets are conditions. We have unary operators (operating on one thing), binary operators (two) and one tertiary operator (forget about that one).
You cannot construct something like your "boundary test" with those easily.
A possible way:
(passnew.Length > 6) && (passcnfrm.Length > 6)
But you aren't testing if the length is equal anyway, even if you could use a syntax like that. You seem to want to compare if both are longer than 6 chars and shorter than 15 chars. One at 7 and one at 14 would satisfy both conditions..
if(passnew.Length == passcnfrm.Length &&
(passnew.Length < 15 && passnew.Length > 6))
{
// ...
}
Checks both are same length, and either one is more than 6 and less than 15 characters long.
that would be:
if(passcnfrm.Length.Equals(passnew.Length))
{
//do stuff
}
A probably better way to do it is:
if (( passnew != null && passcnfrm != null )
( passnew == passcnfrm )
&& ( passnew.Length > 6 && passnew.Length < 15 ))
{
// do stuff
}
Hides the length check inside the equality check which you'll probably need, it isn't in your question but the variable names make it pretty clear you're doing a password change function there. I added the null check to make sure the length checks don't throw a NullReferenceException, not needed in the example because you assign both manually, but might save some trouble if you're going to convert this to a method later on.
You can use like this:
if (s.Contains(s1[i]))
or:
boolean equalsIgnoreCase(String anotherString);
or use this method:
public static int occurrence(string [] a, string a2)
{
int occ = 0;
for (int i = 0; i < a.Length;i++ )
{
if(a[i].Equals(a2))
{
occ++;
}
}
return occ;
}

Are variables shared in recursive functions

I'm trying to calculate the number of success cases within a recursive function in C#, but I'm astonished by the fact that my variable is shared between all the function calls!
[update 2]
More than strange this time. doing so
i = i + validTreesFun(tree.Nodes, newWords.ToList()) ;
resets i to 0
doing this
i = validTreesFun(tree.Nodes, newWords.ToList()) + i ;
gives some results (I'm not sure if it's correct)
[updated : the full code]
public static int validTreesFun(List<Tree<char>> nodes, List<string> words)
{
int i = 0;
if (nodes == null && (words == null || words.Count == 0 || (words.Count == 1 && words.First() == "")))
return 1;
else
if (nodes == null)
return 0;
foreach (Tree<char> tree in nodes)
{
var validWords = words.Where(w => w.ToCharArray()[0] == tree.Root)
.Select(w => w);
if (validWords.Count() == 0)
return 0;
else
{
var newWords = validWords.Select(w => join( w.ToCharArray().Skip(1).ToArray()));
i += validTreesFun(tree.Nodes, newWords.ToList());
}
}
return i;
}
when debuging the variable i take the value 1 but it resets to 0 on the next iteration!!
despite the use of
i = i + ....
What is the problem in that piece of code?
Thank you
if (validWords.Count() == 0)
return 0;
Should be
if (validWords.Count() == 0)
continue;
Also, in general, I personally think it is nicer looking to only send in one element at a time to a recursive function.
public static int validTreesFun(Tree<char> node, List<string> words)
That way you don't get the same kind of mistake like above. Finally, a minor note.
w => w.ToCharArray()[0] == tree.Root
can be written as
w => w[0] = tree.Root
No local variables are not at all shared between recursive calls, you should consider some other design problem, inside and after your foreach loop, I dont see any return statements, can you post full code.
Ok, in debugging you will always observe i's current method's value, debugging is not good in recursive functions, its little hard to understand, you will have to move your control down in Call Stack in order to actually observe value of earlier caller of current function.
I would advice you to output Trace or on log file with your level of node, that will help you actual debugging.
Please use TRACE Statement as follow..
Trace.WriteLine(string.Format("{0},{1}",tree.Name,i));
Local variables are not being shared.
What you are seeing (the reset to 0) is the value of i in the (recursively) called function validTreesFun (i gets set to 0 at the start of the function).
Just looking at your code, I think a possible bug might be in someTestHere - if that is never true, then i will stay 0 in the outer scope. Otherwise it should increment by 1 for each true test.
When you are in debug mode, you indeed see that the i is reseted for the call but remain to the wanted value for the caller. Eg , the stack :
validTreesFun --i = 0 for this one
validTreesFun --i = x for this one, but if you do not go trow the calling stack, you will see 0, which is the good value for the top of the stack

Categories

Resources