so I'm writing a Blackjack game for my Advanced Higher Computing Science project at school, and I have a question about the syntax of the logical operators in VB.
Here's the situation..
If X>Y AND (A=True Or B=True Or C=True) Then
Do something
End IF
Let's say for instance that X is indeed greater than Y, and A is true, but B and C are false. As I understand it the statement will execute, because X is greater than Y, AND at least one of the conditions within the brackets is true, but I'm not entirely sure if this is correct. Can the brackets be used this way for things to be logically correct? Or do I have to write conditions regarding A, B and C separately? For example...
If X>Y AND A=True Then
Do something
End IF
If X>Y AND B=True Then
Do something
End IF
If X>Y AND C=True Then
Do something
End IF
Basically, can the brackets be used as a 'short hand' method to make the code slightly shorter and less cluttered? I'm using the latest version of VB, 2015.
Thanks a lot for any help, I appreciate it!
P.S. - I can't put my actual code on the internet, as this could get me in trouble with my exam board as this is an official assessment.
Consider this original example
If X>Y AND (A=True Or B=True Or C=True) Then
It says, that 2 conditions must be met to evaluate this to True. X must be more than Y and also, condition in parenthesis must evaluate to True. First, lets optimize your code to use .net efficiently
If X>Y AndAlso (A OrElse B OrElse C) Then
In your case, if X>Y evaluates to False there is no reason to continue. Hence, AndAlso. This is a shortcut. Same with OrElse. If A evaluates to true, we don't need to evaluate other conditions - this is supported by your logic. Now, A=True - this is noise. And this is why you name Boolean variables, isSomething, hasSomething, [doneSomething], where doneSomething is a verb, i.e. created, completed, disposed, allowed.
Now, lets look at your second piece of code. Obviously what comes into view first, is that you re-evaluating X>Y 3 times and along, you may do Do something 3 times. This syntax widely used but it would be something along these lines (to create same logic as first evaluation)
If Not X>Y Then
Return ' exit because your first evaluation must be true
End If
If A Then
' Do something
Return ' Success and return
End If
If B Then
' Do something
Return ' Success and return
End If
If C Then
' Do something
Return ' Success and return
End If
Of course, the code above makes little sense because there is obvious repetition. This is better
If Not X>Y Then
Return ' exit because your first evaluation must be true
End If
If A OrElse B OrElse C Then
' Do something
End If
This makes more sense but then again, go to line #2 and use optimized single line code - it will do same.
Related
Today I was working an in-class project with my students when I ran into this bug.
Imgur Link
Pastebin Link
Basically, decTemperature is a String variable that receives an input from the User. In order to teach data validation, short-circuiting, and loops, we were using the following While loop condtionals to force a valid response:
While IsNumeric(decTemperature) = False Or
Convert.ToDecimal(decTemperature) <= 0.0 Or
Convert.ToDecimal(decTemperature) > 135.0
If the user puts in 'abc', in theory the conditional statement should short circuit before reaching the second part of the conditional statement. I attempted the conditional a number of different ways, but ultimately it would crash in every design.
My assumption on the issue probably links closely to an older question I asked about dealing with data types with explicitly setting Option Strict 'on' (although a quick add of Option Strict On in the above code still crashes). That is to say, decTemperature is being processed in each conditional statement before evaluating.
Whatever the case, what is causing the issue and what would be a better approach that still maintains the concepts (that is forcing a valid response from the user)? I have an idea with using a Boolean data type validResponse and setting it, but that seems to be throwing away short-circuiting as a concept.
Or does not short-circuit. Neither does And
OrElse does short-circuit (as well as AndAlso). See OrElse Operator (Visual Basic)
So it should look like this:
While IsNumeric(decTemperature) = False OrElse _
(Convert.ToDecimal(decTemperature) <= 0.0 OrElse _
Convert.ToDecimal(decTemperature) > 135.0)
I would consider using Decimal.TryParse to test the validity of the input.
If you just use Or then every statement is evaluated in every case. That's what the short circuit operators OrElse and AndAlso are for. If you use OrElse the If statement stops the evaluation after the first true statement is detected (or the first false statement in case of an AndAlso).
So in your case the conversion to decimal would be executed in any case. This is avoided with the short circuit operators.
I've been given some code to go through and find problems and things that could be improved and changed (it's a homework task, but this question is unrelated to the task itself), part of the code is:
Function CheckIfSameCell(ByVal FirstCellPosition As CellReference, ByVal SecondCellPosition As CellReference) As Boolean
Dim InSameCell As Boolean
InSameCell = False
If FirstCellPosition.NoOfCellsSouth = SecondCellPosition.NoOfCellsSouth And FirstCellPosition.NoOfCellsEast = SecondCellPosition.NoOfCellsEast Then
InSameCell = True
End If
CheckIfSameCell = InSameCell
End Function
I can't understand why the InSameCell is variable is created, when it can just be assigned to the function name CheckIfSameCell?
Or just use return statements as in the following?
Function CheckIfSameCell(ByVal FirstCellPosition As CellReference, ByVal SecondCellPosition As CellReference) As Boolean
If FirstCellPosition.NoOfCellsSouth = SecondCellPosition.NoOfCellsSouth And FirstCellPosition.NoOfCellsEast = SecondCellPosition.NoOfCellsEast Then
Return True
End If
Return False
End Function
I can understand not returning the expression in the If statement directly, to increase readability.
I know that assigning a return value to the Function name doesn't exit the function, whereas Return does, but is it just a person's style, or is there any advantage to the first version (IMO, the second is more readable)?
Maybe there used to be more checks, where value of InSameCell could change several times and only then get returned. Using return then would change behaviour.
Maybe the author wanted to avoid the tedious renaiming. You know, when you want to rename a function, and you use that function's name many times within its own body, then you have many places to replace, whereas when you introduce a variable you will only have one place to change the name in. (I know the IDE will properly do that for you; but that was not the case in VB6, and habits are difficult to break.)
Maybe the author was much more familiar with VB6 that didn't have return.
Maybe it was a matter of style or policy.
Anyway, I would write it as:
Function CheckIfSameCell(ByVal FirstCellPosition As CellReference, ByVal SecondCellPosition As CellReference) As Boolean
Return FirstCellPosition.NoOfCellsSouth = SecondCellPosition.NoOfCellsSouth AndAlso FirstCellPosition.NoOfCellsEast = SecondCellPosition.NoOfCellsEast
End Function
Assigning the result to the function name is an old style used in VB6 and should not be used any more in VB.NET. Use Return value!
Personally I dislike statements in the style
If condition Then
Return True
Else
Return False
End If
They are just stupid, since condition already yields the return value! Better:
Return condition
It is also the solution chosen by GSerg.
Nobody would write
If x + y = 0 Then
Return 0
ElseIf x + y = 1 Then
Return 1
ElseIf x + y = 2 Then
Return 2
ElseIf x + y = 3 Then
Return 3
...
But some people are constantly doing it when the expression is of type Boolean. I think that they do not realize that conditions are equivalent to arithmetical expressions. They are just arithmetic with Booleans instead of arithmetic with numbers.
Another misconception is that an If-statement requires some comparison like If x > 0 Then. If they have a Boolean variable b they write If b = True Then. But all the If-statement needs is a Boolean value given by a Boolean expression. This expression can be as simple as querying a variable: If b Then.
Why does this work? Because if b is True then b = True yields True and if b is False then b = True yields False. So, b = True is very much like saying x * 1. Of course, this is the same as just x.
The second method is more readable, I concur. It also happens to be my preference for returning out of methods. I really cannot think of a single downside to the latter in comparision, but can for the former. What happens if the method gets longer and someone forgets to set a Boolean flag? A subtle bug would be born. Additionally, it takes more code to write as well. In the latter approach, the code won't compile if it is missing a return, and it also will be shorter.
The only time you need local variables for the return type is when the routine needs to do some other work after the return value is first determined. In the example you post, this is not the case.
Code Complete, 2nd Edition agrees on page 391:
Use a return when it enhances readability In certain routines, once
you know the answer, you want to return it to the calling routine
immediately. If the routine is defined in such a way that it doesn’t
require any further cleanup once it detects an error, not returning
immediately means that you have to write more code.
NOTE: As other answers [1,2] have mentioned, you can reduce the method to a single code statement. Also using AndAlso should help speed up the evaluation by short-circuiting the logical expression early if the first part is false:
Return FirstCellPosition.NoOfCellsSouth = SecondCellPosition.NoOfCellsSouth
AndAlso FirstCellPosition.NoOfCellsEast = SecondCellPosition.NoOfCellsEast
There is one important thing with return and assigning value the the function name. If you (for whatever twisted reason) would like to write something like that
Public Function TestFunct() as Boolean
Dim testVar as Boolean = True
If testVar then
TestFunct = True
Else
TestFunct = False
EndIf
'do more stuff here
...
TestFunct = False
End Function
It will always return false. If you use returns instead it the execution will stop and the function will return correct value.
You might use a variable if for some reason it needs to appear on the right-hand side of an assignment, and you don't want to cause a recursion:
Dim Function F() As Boolean
F = True
If a = b Then
F = Not F()
End If
End Function
In short - Yes your last example is quite valid.
However, most examples used in homework are either used to show other teaching examples. The code in the homework sheet merely shows the basics of using functions in the traditional way and your 2nd example shows the next learning step and is the most compact way of achieving the desired result.
Also, the 1st example could also be used to re-enforce lessons learned earlier - e.g. about assigning variables, use of booleans etc.
One of the best ways to improve your coding skills is to repeatedly practice what you have learned.
I've recently graduated and started a real job. In our training they've been exposing us to VB.NET and a lot of the features they use here. In some of the examples, they've used Select statements (and in a few places they were used where an If/Else really should have been used).
The only time that I've used a switch/select statement in other languages (other than assignments that required it) has been when I wanted the fall through to the next statement.
Given than VB.NET has no fall through, what (if any) cases are there to use the Select statement? Are there any cases when it provides advantages over and If/ElseIf statement?
Select Case, not just Select.
To me, it's one of the best features of the language.
It's much more visual when you have several possible values to test against.
select case some_var
case 1
something()
case 2
something_else()
case 3
etc()
end select
It's much more readable when it comes to testing ranges:
select case some_var
case 1 to 10
something()
case 20 to 30
something_else()
case is > 100
etc()
end select
It's much more readable when you have a bunch of more complex conditions to test, making sure only one is selected:
select case true
case string.isnullorempty(a_string)
something()
case a_string.length < 5
something_else()
case a_string = b_string
etc()
end select
It's superior to C/C++ switch in the sense that it allows expressions as branching points, not just constants.
When using constants as branching points (example 1), compiler is able to generate a more optimised code with direct jumps.
Select tells the compiler that every compare (If) in the analogous set of If/Else blocks is on the same value, and this allows it to make certain optimizations that are harder to be sure of otherwise. For example, it might be more eager to generate machine code that holds that value in a cpu register (that's just hypothetical... different compilers can do what they want).
Also, some of us find Select a lot more readable. It is important to follow the coding standards of whatever team or unit you find yourself.
First off, VB does have fall through, it's just not as obvious. The "fallthrough" in VB is just setting one case to have multiple values:
Dim number As Integer = 8
Select Case number
Case 6,7,8
' do stuff
Case Else
' do default stuff
End Select
As for its advantages, it's way easier to write one Select statement than say, more than three If/ElseIf statements that all test against the same value.
If you are going to do several different things based on the input comparison/range comparison if it's if-elseif+ then use Select instead of crazy if-elseif blocks.
VB.NET's Select statement has some cool features as well, so ensure that you know all the features.
There is a situation where Select Case can be much more efficient than If: when you have a list of "Or" clauses in the If condition and you do not need to evaluate them all to establish the truth of the condition. Suppose you had an if statement such as this:
If A() Or B() Then
DoSomething()
ElseIF C() or D() Then
DoSomethingElse()
Else
DoTheDefault()
EndIF
In this case, to evaluate the first if statement, both functions A() and B() are executed, and similarly for the second if statement when A() and B() are both false. If A() returns true, then the value of B() is immaterial and, unless it changes the program state in a way that you actually want it to (generally not good practice), the execution of B() is redundant. The compiler is constrained by the requirement that all parts of the test MUST be executed before concluding on a value (optimisation of the test is not allowed according to the language spec).
You could separate the conditions into multiple IfElse statements to optimise it yourself but this makes the code less readable and increases the danger of errors when changes are made later. I find that using Select Case is better in this situation:
Select Case True
Case A(), B()
DoSomething()
Case C(), D()
DoSomethingElse()
Case Else
DoTheDefault()
End Select
Now, if A() returns True then B() is not evaluated at all. The evaluation of the conditions is in the sequence listed, so you can help to optimise your code by putting the tests in the order of most likely to return True or least expensive to execute (depending on the application).
If I have the following ...
a OrElse b
... and a is True then clearly b is never evaluated. But if I add an Or, then what?
a OrElse b Or c
Does/should c get evaluated? And what if I put in some brackets?
Apologies if this is basic. Of course I can test for the answer myself but I can't find this question answered here or elsewhere. Lots of questions dealing with Or versus OrElse but nothing dealing with Or with OrElse
OrElse short circuits between the left and right side parameters (only 2 parameters). So I would say that C will always be evaluated as you could treat this as (A OrElse B) Or C.
MSDN OrElse
This is an operator precedence problem. The relevant documentation is here:
http://msdn.microsoft.com/en-us/library/fw84t893.aspx?ppud=4
The important excerpts:
Operators with equal precedence are evaluated left to right in the order in which they appear in the expression.
and
Inclusive disjunction (Or, OrElse)
So what we learn here is that Or and OrElse have the same precedence and that operators with the same precedence are evaluated from left to right.
Therefore, I would expect that in cases where a is true, b is not evaluated. However, c still will be. In cases where a is false, b is evaluated and regardless of the b's value the Or operator will evaluate c. So, yes, c is always evaluated.
As a practical matter, you should generally prefer OrElse in your code unless you have a good reason to use Or. Or exists now mainly for backwards compatibility.
In the case presented, c is evaluated. A small test will tell you:
Debug.WriteLine(test(1) OrElse test(2) Or test(3))
Function test(ByVal a As Integer) As Boolean
Debug.WriteLine(a)
Return True
End Function
The above example outputs:
1
3
True
In my personal experience VB tends to obtain the value for all of them regardless of whether they be actually evaulated or not.
This is only helpfull when order matters for items existance and the like. Just wanted to note it.
When I'm using an If statement and I want to check if a boolean is false should I use the "Not" keyword or just = false, like so
If (Not myboolean) then
vs
If (myboolean = False) then
Which is better practice and more readable?
Definitely, use "Not". And for the alternately, use "If (myboolean)" instead of "If (myboolean = true)"
The works best if you give the boolean a readable name:
if (node.HasChildren)
Since there's no functional difference between either style, this is one of those things that just comes down to personal preference.
If you're working on a codebase where a standard has already been set, then stick to that.
Use True and False to set variables, not to test them. This improves readability as described in the other answers, but it also improves portability, particularly when best practices aren't followed.
Some languages allow you to interchange bool and integer types. Consider the contrived example:
int differentInts(int i, int j)
{
return i-j; // Returns non-zero (true) if ints are different.
}
. . .
if (differentInts(4, 8) == TRUE)
printf("Four and Eight are different!\n");
else
printf("Four and Eight are equal!\n");
Horrible style, but I've seen worse sneak into production. On other people's watches, of course. :-)
Additionally to the consensus, when there is both a true case and a false case please use
if (condition)
// true case
else
// false case
rather than
if (not condition)
// false case
else
// true case
(But then I am never sure if python's x is not None is the true-case or the false case.)
Definitely use "Not", consider reading it aloud.
If you read aloud:
If X is false Then Do Y
Do Y
Versus
If Not X Then Do Y
I think you'll find the "Not" route is more natural. Especially if you pick good variable names or functions.
Code Complete has some good rules on variable names. http://cc2e.com/Page.aspx?hid=225 (login is probably required)
! condition
In C and pre-STL C++, "!condition" means condition evaluates to a false truth value, whereas "condition == FALSE" meant that the value of condition had to equal what the system designed as FALSE. Since different implementations defined it in different ways, it was deemed better practice to use !condition.
UPDATE: As pointed out in the comment -- FALSE is always 0, it's TRUE that can be dangerous.
Something else: Omit the parentheses, they’re redundant in VB and as such, constitute syntactic garbage.
Also, I'm slightly bothered by how many people argue by giving technical examples in other languages that simply do not apply in VB. In VB, the only reasons to use If Not x instead of If x = False is readability and logic. Not that you’d need other reasons.
Completely different reasons apply in C(++), true. Even more true due to the existence of frameworks that really handle this differently. But misleading in the context of VB!
It does not make any difference as long you are dealing with VB only, however if you happen to use C functions such as the Win32 API, definitely do not use "NOT" just "==False" when testing for false, but when testing for true do not use "==True" instead use "if(function())".
The reason for that is the difference between C and VB in how boolean is defined.
In C true == 1 while in VB true == -1 (therefore you should not compare the output of a C function to true, as you are trying to compare -1 to 1)
Not in Vb is a bitwise NOT (equal to C's ~ operator not the ! operator), and thus it negates each bit, and as a result negating 1 (true in C) will result in a non zero value which is true, NOT only works on VB true which is -1 (which in bit format is all one's according to the two's complement rule [111111111]) and negating all bits [0000000000] equals zero.
For a better understanding see my answer on Is there a VB.net equivalent for C#'s ! operator?
Made a difference with these lines in vb 2010/12
With the top line, Option Strict had to be turned off.
If InStr(strLine, "=") = False Then _
If Not CBool(InStr(strLine, "=")) Then
Thanks for answering the question for me. (I'm learning)